我正在尝试使用2D HUD,其中的图标可以在3D环境中跟踪HUD后面3D对象屏幕上的位置。
推理:有时您无法看到3D对象(太远或离屏幕),但您仍然想知道它在哪里。
问题: 3D场景使用透视矩阵对其进行变换,给出深度(z轴),HUD严格为2D(xy平面)。由于深度,2D HUD无法在物体越来越近时正确跟踪物体。
我想要的是什么:一种获取2D矢量[(x,y)pos]的方法,其中放置一个图标,使其位于背景中3D对象的中心位置。
xy-plane中所有对象的示例(z = 0):
你可以看到,当物体离中心越来越远时,Icon(白色的圆圈)更偏离中心。
深度越来越远的物体示例(离中心越远==越深):
你可以看到HUD认为3D物体仍在同一个平面上。
伪码:
.getPos()获取Vector(x,y,z)
lookAtObj = Object.getPos() - camera.getPos() // lookAt vector from camera to the object
icon.pos = Orthogonal Component of lookAtObj on camera.get_lookAt()
我的观点矩阵:
// Function call in the OpenGL draw() method
FloatMatrix proj = FloatMatrix.getPerspectiveMatrix( this.fov, this.width, this.height, 0.1f, 200.0f );
// Function
public static FloatMatrix getPerspectiveMatrix( Double fov, float w, float h, float near, float far ){
float asp = w/h;
float fov_cos = (float) Math.cos( fov / 2.0d );
float fov_sin = (float) Math.sin( fov / 2.0d );
float fov_cot = fov_cos/fov_sin;
float a_0 = fov_cot/asp;
float a_3 = (far + near)/(near-far);
float a_43 = (2.0f * far * near)/(near-far);
float[] an = {
a_0, 0.0f, 0.0f, 0.0f,
0.0f, fov_cot, 0.0f, 0.0f,
0.0f, 0.0f, a_3, -1.0f,
0.0f, 0.0f, a_43, 0.0f,
};
return new FloatMatrix( an, 4, 4 );
}
答案 0 :(得分:2)
这非常简单。您可以使用gluProject
。它将采用给定的模型视图,投影和视口变换以及3D点,并应用反向并在窗口坐标中为您吐出2D点(对于小错别字道歉,只需在此处键入):
double myX = ..., myY = ..., myZ = ...; // your object's 3d coordinates
double[] my2DPoint = new double[2]; // will contain 2d window coords when done
double[] modelview = new double[16];
double[] projection = new double[16];
int[] viewport = new int[4];
gl.glGetDoublev(GL2.GL_MODELVIEW_MATRIX, modelview, 0);
gl.glGetDoublev(GL2.GL_PROJECTION_MATRIX, projection, 0);
gl.glGetIntegerv(GL2.GL_VIEWPORT, viewport, 0);
glu.gluProject(myX, myY, myZ, modelview, 0, projection, 0,
viewport, 0, my2DPoint, 0);
// now my2DPoint[0] is window x, and my2DPoint[1] is window y
执行此操作后,您将在2D窗口坐标中获得3D点。然后只需将投影切换到2D正交投影,在窗口像素中,然后在2D空间中绘制HUD。
为了表现,如果每帧有多个HUD项目;只需每帧获取一次modelview / projection / viewport(或者更好的是,如果你更改它们并根据需要重新查询,则使缓存的无效)并在后续调用gluProject
时重用它们。