gpt4 book ai didi

java - 如何使用 JOML 模拟 OpenGL 之类的模型,在 3D 投影到 2D 平面上查看矩阵?

转载 作者:行者123 更新时间:2023-12-04 08:52:49 24 4
gpt4 key购买 nike

经过多年的 OpenGL 初学者类(class)和线性代数类(class),我最近终于明白了模型、 View 和投影矩阵的意义。基本上,模型矩阵将 3D 模型的顶点坐标转换为 3D 世界中的顶点坐标(相对于 3D 世界的原点平移、旋转和缩放模型)。 View 矩阵将 3D 世界的顶点坐标转换为相对于相机的顶点坐标(通常只有世界相对于相机的平移和旋转),投影矩阵用于计算/转换相机 View 中的顶点坐标为在 2D 平面(通常是屏幕)上的投影。
我正在尝试在没有 OpenGL 的 2D 平面上的 3D 投影中创建相机系统,但是通过使用 JOML,这是一个用于 OpenGL 的 Java 数学(主要是线性代数数学)库,经常与 LightWeight Java 游戏库 3 一起使用。我能够在 OpenGL 中创建相机系统,使用上述 3 个矩阵非常容易。但是当我使用相同的精确矩阵(以及一些额外的代码以便投影出现在屏幕上)时,我只能在 2D 平面上进行投影。模型矩阵和 View 矩阵似乎对模型在屏幕上的投影方式没有任何影响。
这是我用来在屏幕上投影立方体的代码:

private float theta = 0;

@Override
public void render(Graphics g) {

Vector3f cube3f[][] = {

// SOUTH
{ new Vector3f(-0.5f, -0.5f, -0.5f), new Vector3f(-0.5f, 0.5f, -0.5f), new Vector3f( 0.5f, 0.5f, -0.5f) },
{ new Vector3f(-0.5f, -0.5f, -0.5f), new Vector3f( 0.5f, 0.5f, -0.5f), new Vector3f( 0.5f, -0.5f, -0.5f) },

// EAST
{ new Vector3f( 0.5f, -0.5f, -0.5f), new Vector3f( 0.5f, 0.5f, -0.5f), new Vector3f( 0.5f, 0.5f, 0.5f) },
{ new Vector3f( 0.5f, -0.5f, -0.5f), new Vector3f( 0.5f, 0.5f, 0.5f), new Vector3f( 0.5f, -0.5f, 0.5f) },

// NORTH
{ new Vector3f( 0.5f, -0.5f, 0.5f), new Vector3f( 0.5f, 0.5f, 0.5f), new Vector3f(-0.5f, 0.5f, 0.5f) },
{ new Vector3f( 0.5f, -0.5f, 0.5f), new Vector3f(-0.5f, 0.5f, 0.5f), new Vector3f(-0.5f, -0.5f, 0.5f) },

// WEST
{ new Vector3f(-0.5f, -0.5f, 0.5f), new Vector3f(-0.5f, 0.5f, 0.5f), new Vector3f(-0.5f, 0.5f, -0.5f) },
{ new Vector3f(-0.5f, -0.5f, 0.5f), new Vector3f(-0.5f, 0.5f, -0.5f), new Vector3f(-0.5f, -0.5f, -0.5f) },

// TOP
{ new Vector3f(-0.5f, 0.5f, -0.5f), new Vector3f(-0.5f, 0.5f, 0.5f), new Vector3f( 0.5f, 0.5f, 0.5f) },
{ new Vector3f(-0.5f, 0.5f, -0.5f), new Vector3f( 0.5f, 0.5f, 0.5f), new Vector3f( 0.5f, 0.5f, -0.5f) },

// BOTTOM
{ new Vector3f( 0.5f, -0.5f, 0.5f), new Vector3f(-0.5f, -0.5f, 0.5f), new Vector3f(-0.5f, -0.5f, -0.5f) },
{ new Vector3f( 0.5f, -0.5f, 0.5f), new Vector3f(-0.5f, -0.5f, -0.5f), new Vector3f( 0.5f, -0.5f, -0.5f) },

};

Vector4f cube4f[][] = new Vector4f[cube3f.length][cube3f[0].length];

for(int i = 0; i < cube3f.length; i++) {
for(int j = 0; j < cube3f[i].length; j++) {

Matrix4f modelMatrix = new Matrix4f()
.rotate((float)Math.toRadians(theta), new Vector3f(0.0f, 1.0f, 0))
.rotate((float)Math.toRadians(theta), new Vector3f(1.0f, 0, 0))
.translate(new Vector3f(0, 5, 5)); // this is supposed to move the cube up 5 units and away 5 units
Vector4f tempvec = new Vector4f(cube3f[i][j], 0.0f).mul(modelMatrix);
Matrix4f viewMatrix = new Matrix4f().translate(new Vector3f(theta, 0, -20)); //this is supposed to translate the camera back 20 units
tempvec = tempvec.mul(viewMatrix);
Matrix4f projectionMatrix = new Matrix4f().identity().setPerspective((float)Math.toRadians(70.0f), 1280.0f/720.0f, 0.1f, 1000.0f);
cube4f[i][j] = tempvec.mul(projectionMatrix);

//following code makes the projection appear inside the screen's borders
cube4f[i][j].x += 1.0f;
cube4f[i][j].y += 1.0f;
cube4f[i][j].x *= 0.5f * 1280.0f;
cube4f[i][j].y *= 0.5f * 720.0f;

}
}

Graphics2D g2d = (Graphics2D)g;
g2d.setBackground(new Color(32, 32, 32, 255));
g2d.clearRect(0, 0, 1280, 720);

g2d.setColor(Color.WHITE);

for(int i = 0; i < cube4f.length; i++) {
g2d.drawLine((int)cube4f[i][0].x, (int)cube4f[i][0].y, (int)cube4f[i][1].x, (int)cube4f[i][1].y);
g2d.drawLine((int)cube4f[i][1].x, (int)cube4f[i][1].y, (int)cube4f[i][2].x, (int)cube4f[i][2].y);
g2d.drawLine((int)cube4f[i][2].x, (int)cube4f[i][2].y, (int)cube4f[i][0].x, (int)cube4f[i][0].y);
}
}

@Override
public void update() {
theta++;
}
在上面的代码中,立方体应该距离相机 25 个单位(因为立方体距离世界原点 5 个单位,而相机在相反方向上距离世界 20 个单位)和向右 5 个单位世界的。但事实并非如此,如下图所示:
up-close centered rotating cube
正如我们在图片中看到的那样;立方体清晰居中,可以近距离观察。
我试图找到一个解决方案,让我在我的 LWJGL3 应用程序和我的 3D 投影应用程序上保留相同的“OpenGL”基本代码(更准确地说是 JOML 基本代码)。即使用相同的模型、 View 和投影矩阵在两个应用程序上生成相同的投影。

最佳答案

您错过了 Perspective divide .剪辑空间坐标是 Homogeneous coordinates .您必须将 Homogeneous 裁剪空间坐标转换为 Cartesian归一化设备坐标(所有组件都在 [-1, 1] 范围内)除以 x , yz组件由 w成分:

tempvec = tempvec.mul(projectionMatrix);
cube4f[i][j] = new Vector4f(
tempvec.x / tempvec.w,
tempvec.y / tempvec.w,
tempvec.z / tempvec.w,
1.0f);

由于顶点是点而不是 vector ,顶点坐标的第 4 个分量必须是 1 而不是 0: Vector4f tempvec = new Vector4f(cube3f[i][j], 0.0f).mul(modelMatrix);
Vector4f tempvec = new Vector4f(cube3f[i][j], 1.0f).mul(modelMatrix);

关于java - 如何使用 JOML 模拟 OpenGL 之类的模型,在 3D 投影到 2D 平面上查看矩阵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64012912/

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