After two hours of googling (here, here, here, here, and here, and a ton others which I am not bothered to find), I thought I had finally learnt the theory of turning 3D coordinates to 2D coordinates. But it isn't working. The idea is to translate the 3D coordinates of a ship to 2D coordinates on the screen to render the username of the player controlling that ship.
经过两个小时的谷歌搜索(这里,这里,这里,这里,这里,以及其他一些我不想找到的东西),我以为我终于学会了将3D坐标转换为2D坐标的理论。但它没有用。我们的想法是将船舶的3D坐标转换为屏幕上的2D坐标,以呈现控制该船舶的玩家的用户名。
However, the text is rendering in the wrong location:
但是,文本呈现在错误的位置:
The text is "Test || 2DXCoordinate || 2DZCoordinate".
文本是“Test || 2DXCoordinate || 2DZCoordinate”。
Here is my getScreenCoords()
- Which converts the 3D coordinates to 2D.
这是我的getScreenCoords() - 它将3D坐标转换为2D。
public static int[] getScreenCoords(double x, double y, double z) {
FloatBuffer screenCoords = BufferUtils.createFloatBuffer(4);
IntBuffer viewport = BufferUtils.createIntBuffer(16);
FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
FloatBuffer projection = BufferUtils.createFloatBuffer(16);
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelView);
GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
boolean result = GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);
if (result) {
return new int[] { (int) screenCoords.get(0), (int) screenCoords.get(1) };
}
return null;
}
screenCoords.get(0) is returning a perfect X coordinate. However, screenCoords.get(1) is going higher or lower depending on how far away I am from the ship. After many hours of debugging, I have narrowed it down to this line being incorrect:
screenCoords.get(0)返回一个完美的X坐标。但是,screenCoords.get(1)会根据我离船的距离而变高或变低。经过几个小时的调试,我把它缩小到这条线是不正确的:
GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);
However, I have no idea what is wrong. The X coordinate of the ship is fine.... Why not the Y?
但是,我不知道出了什么问题。船的X坐标很好....为什么不是Y?
According to BDL's answer, I am supplying the "wrong matrix" to gluProject(). But I don't see how that is possible, since I call the method right after I render my ship (Which is obviously in whatever matrix draws the ship).
根据BDL的回答,我向gluProject()提供了“错误的矩阵”。但我不知道这是怎么可能的,因为我在渲染我的船之后立即调用了这个方法(这显然是在任何矩阵划船的情况下)。
I just can't fathom what is wrong.
我无法理解什么是错的。
Note: BDL's answer is perfectly adequate except that it does not explain why the Y coordinates are incorrect.
注意:BDL的答案是完全足够的,除了它没有解释为什么Y坐标不正确。
Note: This question used to be much longer and much more vague. I have posted my narrowed-down question above after hours of debugging.
注意:这个问题过去时间更长,更模糊。我经过几个小时的调试后发布了上面缩小的问题。
2 个解决方案
#1
6
You have to use the same projection matrix in gluProject that you use for rendering your ship. In your case the ship is rendered using a perspective projection, but when you call gluProject a orthographic projection is used.
您必须在用于渲染船只的gluProject中使用相同的投影矩阵。在您的情况下,使用透视投影渲染船只,但是当您调用gluProject时,会使用正交投影。
General theory about coordinate systems in OpenGL
关于OpenGL中坐标系的一般理论
In most cases geometry of a model in your scene (e.g. the ship) is given in a model-coordinate system. This is the space where your vertex coordinates exist. When now placing the model in your scene we apply the model-matrix to each vertex to get the coordinates the ship has in the scene. This coordinate system is called world space. When viewing the scene from a given viewpoint and a viewing direction, again a transformation is needed that transforms the scene such that the viewpoint is located in the origin (0,0,0) and view-direction is along the negativ z-axis. This is the view coordinate system. The last step is to transform view-coordinates into ndc, which is done via a projection matrix.
在大多数情况下,场景中模型的几何形状(例如船舶)在模型坐标系中给出。这是顶点坐标存在的空间。现在将模型放置在场景中时,我们将模型矩阵应用于每个顶点以获得船舶在场景中的坐标。这个坐标系称为世界空间。当从给定视点和观察方向观察场景时,还需要变换场景以使得视点位于原点(0,0,0)并且视图方向沿着负z轴。这是视图坐标系。最后一步是将视图坐标转换为ndc,这是通过投影矩阵完成的。
In total we get the transformation of a vertex to the screen as:
总的来说,我们将顶点转换为屏幕:
v_screen = Projection * View * Model * v_model
In ancient OpenGL (as you use it) View and Model are stored together in the ModelView matrix.
在古老的OpenGL中(当您使用它时)视图和模型一起存储在ModelView矩阵中。
(I skipped here some problems as perspective divide, but it should be sufficient to understand the problem.)
(我在这里略过了一些问题,因为视角分歧,但它应该足以理解这个问题。)
Your problem
You already have a position in world space (x,y,z) of your ship. Thus the transformation with Model has already happend. What is left is
您已经在船的世界空间(x,y,z)中占有一席之地。因此,模型的转变已经发生。剩下的是
v_screen = Projection * View * v_worldspace
For this we see, that in our case the ModelView matrix that gets entered to gluProject has to be exactly the View matrix.
为此我们看到,在我们的例子中,输入到gluProject的ModelView矩阵必须完全是View矩阵。
I can't tell you where you get the view matrix in your code, since I don't know this part of your code.
我无法告诉你在代码中获取视图矩阵的位置,因为我不知道代码的这一部分。
#2
0
I found an answer to my issue!
我找到了问题的答案!
I used
font.drawString(drawx - offset, drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);
When it should have been
什么时候应该
font.drawString(drawx - offset, Display.getHeight() - drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);
#1
6
You have to use the same projection matrix in gluProject that you use for rendering your ship. In your case the ship is rendered using a perspective projection, but when you call gluProject a orthographic projection is used.
您必须在用于渲染船只的gluProject中使用相同的投影矩阵。在您的情况下,使用透视投影渲染船只,但是当您调用gluProject时,会使用正交投影。
General theory about coordinate systems in OpenGL
关于OpenGL中坐标系的一般理论
In most cases geometry of a model in your scene (e.g. the ship) is given in a model-coordinate system. This is the space where your vertex coordinates exist. When now placing the model in your scene we apply the model-matrix to each vertex to get the coordinates the ship has in the scene. This coordinate system is called world space. When viewing the scene from a given viewpoint and a viewing direction, again a transformation is needed that transforms the scene such that the viewpoint is located in the origin (0,0,0) and view-direction is along the negativ z-axis. This is the view coordinate system. The last step is to transform view-coordinates into ndc, which is done via a projection matrix.
在大多数情况下,场景中模型的几何形状(例如船舶)在模型坐标系中给出。这是顶点坐标存在的空间。现在将模型放置在场景中时,我们将模型矩阵应用于每个顶点以获得船舶在场景中的坐标。这个坐标系称为世界空间。当从给定视点和观察方向观察场景时,还需要变换场景以使得视点位于原点(0,0,0)并且视图方向沿着负z轴。这是视图坐标系。最后一步是将视图坐标转换为ndc,这是通过投影矩阵完成的。
In total we get the transformation of a vertex to the screen as:
总的来说,我们将顶点转换为屏幕:
v_screen = Projection * View * Model * v_model
In ancient OpenGL (as you use it) View and Model are stored together in the ModelView matrix.
在古老的OpenGL中(当您使用它时)视图和模型一起存储在ModelView矩阵中。
(I skipped here some problems as perspective divide, but it should be sufficient to understand the problem.)
(我在这里略过了一些问题,因为视角分歧,但它应该足以理解这个问题。)
Your problem
You already have a position in world space (x,y,z) of your ship. Thus the transformation with Model has already happend. What is left is
您已经在船的世界空间(x,y,z)中占有一席之地。因此,模型的转变已经发生。剩下的是
v_screen = Projection * View * v_worldspace
For this we see, that in our case the ModelView matrix that gets entered to gluProject has to be exactly the View matrix.
为此我们看到,在我们的例子中,输入到gluProject的ModelView矩阵必须完全是View矩阵。
I can't tell you where you get the view matrix in your code, since I don't know this part of your code.
我无法告诉你在代码中获取视图矩阵的位置,因为我不知道代码的这一部分。
#2
0
I found an answer to my issue!
我找到了问题的答案!
I used
font.drawString(drawx - offset, drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);
When it should have been
什么时候应该
font.drawString(drawx - offset, Display.getHeight() - drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);