0

我正在尝试在我的游戏中使用 gluProject。我找到了一种使用它的方法,但我不知道如何处理轮换。

这是我制作的代码:

public static Vector2 getScreenCoordinates(float x, float y, float z, int height, int width)
{
    FloatBuffer screen_coords = GLAllocation.createDirectFloatBuffer(4);
    IntBuffer viewport = GLAllocation.createDirectIntBuffer(16);
    FloatBuffer modelview = GLAllocation.createDirectFloatBuffer(16);
    FloatBuffer projection = GLAllocation.createDirectFloatBuffer(16);

    GL11.glGetFloat(2982, modelview);
    GL11.glGetFloat(2983, projection);
    GL11.glGetInteger(2978, viewport);

    boolean result = GLU.gluProject(x, y, z, modelview, projection, viewport, screen_coords);
    if (result)
    {
        float screen_x = screen_coords.get(0);
        float screen_y = screen_coords.get(1);
        float scrren_z = screen_coords.get(2);

        screen_y -= height / 2;
        screen_y = -screen_y;
        screen_y += height / 2;

        return new Vector2(screen_x, screen_y);
    }
    else
    {
         System.out.printf("Failed to convert 3D coords to 2D screen coords");
         return null;
    }
}

所以x和是我的 3D 地图yz的坐标。height并且width是我的窗口大小。

如何修改它以处理旋转(偏航和俯仰)?

谢谢。


这是我的新代码:

public Vector2 worldToScreen(double x, double y, double z, int yaw, int pitch)
{   
    // Initialize the result buffer
    FloatBuffer screen_coords = GLAllocation.createDirectFloatBuffer(4);

    // Init the OpenGL buffers
    IntBuffer viewport = GLAllocation.createDirectIntBuffer(16);
    FloatBuffer modelview = GLAllocation.createDirectFloatBuffer(16);
    FloatBuffer projection = GLAllocation.createDirectFloatBuffer(16);

    // Add the rotation
    GL11.glRotatef(yaw, 0, 0, 1);
    GL11.glRotatef(pitch, 1, 0, 0);

    // Get the OpenGL data
    GL11.glGetFloat(2982, modelview);
    GL11.glGetFloat(2983, projection);
    GL11.glGetInteger(2978, viewport);

    // Remove the rotation
    GL11.glRotatef(-yaw, 0, 0, 1);
    GL11.glRotatef(-pitch, 1, 0, 0);

    // Calculate the screen position
    boolean result = GLU.gluProject(x, y, z, modelview, projection, viewport, screen_coords);

    if (result)
    {
        if ( (screen_coords.get(0) < -1.0f) || (screen_coords.get(0) > 1.0f) || (screen_coords.get(1) < -1.0f) || (screen_coords.get(1) > 1.0f) )
            return null;

        int window_half_width = getWidth() / 2;
        int window_half_height = getHeight() / 2;

        int screen_x = window_half_width + (window_half_width * -screen_coords.get(0));
        int screen_y = window_half_height + (window_half_height * screen_coords.get(1));

        System.out.printf("(Full Screen / No bounds) [" +x+ ", " +y+ ", " +z+ "] gives [" +screen_coords.get(0)+ ", " +screen_coords.get(1)+ "]");
        System.out.printf("(Every Time) [" +x+ ", " +y+ ", " +z+ "] gives [" +screen_x+ ", " +screen_y+ "]");
        return new Vector2(screen_x, screen_y);
    }
    else
    {
        System.out.printf("Failed to convert 3D coords to 2D screen coords");
        return null;
    }
}

那是对的吗?

4

1 回答 1

1

Yaw 是围绕 y 轴的旋转(指向上方),pitch 是围绕 x 轴的旋转。

GL11.glRotatef(pitch, 1, 0, 0);
GL11.glRotatef(yaw, 0, 1, 0);

推送/弹出投影矩阵也可能更快,并且您应该处于正确的矩阵模式。(您的模型视图矩阵和投影矩阵都必须正确)。

GL11.glPushMatrix();
// Camera rotations
GL11.glPopMatrix();

但是,为什么您需要撤消相机转换是值得怀疑的。您可能应该每帧或视口只应用一次它们。使用该视图渲染场景,然后获取投影坐标,然后更改为 2D 渲染模式。

更新

如果您使用相机的滚动、俯仰和偏航来表示它们在 OpenGL 坐标系中的实际含义——相对于相机,我会更喜欢它。关键是,只要您正确设置了相机模型视图和投影矩阵,就可以投影该点。您一定已经在某处设置了相机。您将能够查看这是否正确,因为您可以看到结果。应用该转换,您将知道它是正确的。

它是否正确?有可能?你必须应用所有的转换。完全相同的转换为您提供您在游戏中看到的相机视图。这包括所有平移和旋转。你会知道你是否正确,因为你应该已经在游戏中应用了这些转换。

但是,您需要考虑的是,手头的相机投影矩阵是什么?如果你不知道,调用 glLoadIdentity() 清除它,然后调用你的相机转换逻辑。您需要一个准确的模型视图和投影矩阵 -与您在游戏中使用的完全相同的相机设置。如果您的模型视图或投影矩阵处于错误状态,它将无法正常工作。

于 2012-04-10T11:38:32.940 回答