Java 如何使用JOML模拟类似OpenGL的模型,在3D投影到2D平面上查看矩阵?
在学习了多年OpenGL和线性代数的初级课程后,我最近终于理解了模型、视图和投影矩阵的观点。基本上,模型矩阵将三维模型的顶点坐标转换为三维世界中的顶点坐标(相对于三维世界的原点平移、旋转和缩放模型)。视图矩阵将三维世界的顶点坐标转换为相对于摄影机的顶点坐标(通常仅世界相对于摄影机的平移和旋转),投影矩阵用于将摄影机视图中的顶点坐标计算/转换为二维平面(通常为屏幕)上的投影 我试图在没有OpenGL的情况下,通过使用JOML在2D平面上创建一个3D投影的相机系统,JOML是一个Java数学(主要是线性代数数学)库,用于OpenGL,常用于轻量级Java游戏库3。我能够在OpenGL中创建一个相机系统,使用上面提到的3个矩阵非常简单。但是,当我使用相同的精确矩阵(以及一些额外的代码以便投影显示在屏幕上)时,我只能在二维平面上进行投影。模型矩阵和视图矩阵似乎对模型在屏幕上的投影方式没有任何影响 下面是我用来在屏幕上投影立方体的代码:Java 如何使用JOML模拟类似OpenGL的模型,在3D投影到2D平面上查看矩阵?,java,math,opengl,3d,projection-matrix,Java,Math,Opengl,3d,Projection Matrix,在学习了多年OpenGL和线性代数的初级课程后,我最近终于理解了模型、视图和投影矩阵的观点。基本上,模型矩阵将三维模型的顶点坐标转换为三维世界中的顶点坐标(相对于三维世界的原点平移、旋转和缩放模型)。视图矩阵将三维世界的顶点坐标转换为相对于摄影机的顶点坐标(通常仅世界相对于摄影机的平移和旋转),投影矩阵用于将摄影机视图中的顶点坐标计算/转换为二维平面(通常为屏幕)上的投影 我试图在没有OpenGL的情况下,通过使用JOML在2D平面上创建一个3D投影的相机系统,JOML是一个Java数学(主要是
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++;
}
private float theta=0;
@凌驾
公共空间渲染(图形g){
向量3f立方f[]]={
//南方
{新向量3F(-0.5f,-0.5f,-0.5f),新向量3F(-0.5f,0.5f,-0.5f),新向量3F(0.5f,0.5f,-0.5f)},
{新向量3F(-0.5f,-0.5f,-0.5f),新向量3F(0.5f,0.5f,-0.5f),新向量3F(0.5f,-0.5f,-0.5f)},
//东边
{新向量3F(0.5f,-0.5f,-0.5f),新向量3F(0.5f,0.5f,-0.5f),新向量3F(0.5f,0.5f,0.5f)},
{新向量3F(0.5f,-0.5f,-0.5f),新向量3F(0.5f,0.5f,0.5f),新向量3F(0.5f,-0.5f,0.5f)},
//北
{新向量3F(0.5f,-0.5f,0.5f),新向量3F(0.5f,0.5f,0.5f),新向量3F(-0.5f,0.5f,0.5f)},
{新向量3F(0.5f,-0.5f,0.5f),新向量3F(-0.5f,0.5f,0.5f),新向量3F(-0.5f,-0.5f,0.5f)},
//西部
{新向量3F(-0.5f,-0.5f,0.5f),新向量3F(-0.5f,0.5f,0.5f),新向量3F(-0.5f,0.5f,-0.5f)},
{新向量3F(-0.5f,-0.5f,0.5f),新向量3F(-0.5f,0.5f,-0.5f),新向量3F(-0.5f,-0.5f)},
//顶
{新向量3F(-0.5f,0.5f,-0.5f),新向量3F(-0.5f,0.5f,0.5f),新向量3F(0.5f,0.5f,0.5f)},
{新向量3F(-0.5f,0.5f,-0.5f),新向量3F(0.5f,0.5f,0.5f),新向量3F(0.5f,0.5f,-0.5f)},
//底部
{新向量3F(0.5f,-0.5f,0.5f),新向量3F(-0.5f,-0.5f,0.5f),新向量3F(-0.5f,-0.5f,-0.5f)},
{新向量3F(0.5f,-0.5f,0.5f),新向量3F(-0.5f,-0.5f,-0.5f),新向量3F(0.5f,-0.5f,-0.5f)},
};
Vector4f cube4f[][]=新的Vector4f[cube3f.length][cube3f[0.length];
对于(int i=0;i
在上面的代码中,立方体应该距离摄影机25个单位(因为立方体距离世界原点5个单位,摄影机在相反方向距离世界20个单位),距离世界右侧5个单位。但我们在下图中看到的情况并非如此:
如图所示;立方体清晰居中,近距离观察
我正试图找到一种解决方案,使我能够在LWJGL3应用程序和3D投影应用程序上保留相同的“OpenGL”基本代码(更准确地说是JOML基本代码)。即使用相同的模型、视图和投影矩阵在两个应用程序上生成相同的投影