使用2D HUD图标跟踪3D环境中的对象

时间:2014-03-20 04:08:22

标签: java opengl vector jogl hud

我正在尝试使用2D HUD,其中的图标可以在3D环境中跟踪HUD后面3D对象屏幕上的位置。

推理:有时您无法看到3D对象(太远或离屏幕),但您仍然想知道它在哪里。

问题: 3D场景使用透视矩阵对其进行变换,给出深度(z轴),HUD严格为2D(xy平面)。由于深度,2D HUD无法在物体越来越近时正确跟踪物体。

我想要的是什么:一种获取2D矢量[(x,y)pos]的方法,其中放置一个图标,使其位于背景中3D对象的中心位置。

xy-plane中所有对象的示例(z = 0):

你可以看到,当物体离中心越来越远时,Icon(白色的圆圈)更偏离中心。 Example 1

深度越来越远的物体示例(离中心越远==越深):

你可以看到HUD认为3D物体仍在同一个平面上。 Example 2

伪码:

.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 );

}

1 个答案:

答案 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时重用它们。