2010-09-25 121 views
12

我已经看过很多Screen-Coordinate的世界坐标帖子,但还没有看到相反的情况。从我看过的任何角度看,有没有一种简单的方法可以从3d点获取屏幕坐标?我使用C++和OpenGL如何从3D点获取屏幕坐标? Opengl

+0

这是一个确切的副本http://stackoverflow.com/questions/724219/how-to-convert-a-3d-point-into-2d-perspective-projection/866749#866749 – 2010-09-25 10:53:13

+2

@Mads Elvheim:几乎一个确切的副本。这个问题是针对C++和OpenGL的。另一个问题不是。事实上,另一个问题被标记为“Java”。 – 2011-11-18 19:20:01

回答

4

屏幕坐标的顶点就是它的投影和模型视图矩阵乘法这样顶点的结果:

screen_coordinates = projection_matrix * modelview_matrix * world_coordinates

您可以自己动手完成它(尤其是如果你用一些数学库在基质上做操作),或者使用gluProject,例如:

std::array<GLfloat, 16> projection; 
std::array<GLfloat, 16> modelview; 
std::array<GLfloat, 3> screen_coords; 

glGetFloatv(GL_PROJECTION_MATRIX, projection.data()); 
glGetFloatv(GL_MODELVIEW_MATRIX, modelview.data()); 

gluProject(world_coords[0], world_coords[1], world_coords[2], 
    modelview.data(), projection.data(), 
    screen_coords.data(), screen_coords.data() + 1, screen_coords.data() + 2); 
+1

Downvote。 gluProject做正确的事情,但你的解释不。将一个点与模型视图矩阵和投影矩阵相乘即可​​得出剪辑空间坐标,但*之前*除以w。它不会给你屏幕空间的坐标。见巴巴尔的答案。 – 2010-09-25 10:49:06

+0

要判断它是否提供了正确的空间坐标,您需要更多关于OP的世界设置的详细信息,例如我几乎没有使用视角设置为我的2D游戏。但看起来你的水晶球完美无缺,所以thv为downvote :) – erjot 2010-09-26 21:04:03

+0

PS。不是OpenGL的(固定功能流水线)视口的PROJECTION矩阵包含设置?你需要明确地除以w的情况是什么? GLSL默认是这样做的。你使用的是视口,不管你是否知道,你使用的是 – erjot 2010-09-26 21:09:26

20

erjot的答案是不完整的。

还有两件事要考虑。

  1. homogeneous = P . M . world,homogeneous向量是均匀空间中的4维向量。特别是,要使其回到[-1:1]^3立方体,需要将其前3个坐标除以homogeneous.wcube.x = homogeneous.x/homogeneous.w(有人称之为投影鸿沟)。
  2. 然后,您需要通过对其应用视口转换将[-1:1]^3立方体转换为窗口坐标。 window.x = viewport.x + viewport.width * (cube.x+1)/2

如果你关心最终的Z,转换不是通过视口,而是通过DepthRange。

2

另一件事。记住,gluProject给出坐标系的起点在左下角开始的坐标。屏幕坐标从左上角开始。为了获得正确的屏幕坐标值,必须从OpenGL设备的高度中减去y的值。

例如,在Qt的GLWidget绘制在(0,1,2)世界坐标不言而喻文本:

gluProject(0,1,2,modelMatrix,projMatrix,sc.x,sc.y, sc.z); renderText(sc.x,height() - sc.y,“(0,1,2)”);