opengl得到窗口空间到世界空间光标位置

jobtbby3  于 2023-01-08  发布在  其他
关注(0)|答案(1)|浏览(135)

我正在尝试使用viewprojectionmatrix从窗口空间(-1,1窗口宽度和高度)获取鼠标光标到世界空间pos。
这是我如何计算我的投影矩阵:

static mat4 Perspective4x4(float FOV, float AspectRatio, float FarC, float NearC)
{
    // Positive x is right
    // Positive y is up
    // Positive z is forward into the screen

    float Cotangent = 1.0f / tanf((FOV)*0.5f);
    float Depth = NearC - FarC;
    float A = (-FarC - NearC) / Depth;
    float B = 2.0f * FarC * NearC / Depth;
    return
    {
        Cotangent/AspectRatio, 0.0f, 0.0f, 0.0f,
        0.0f, Cotangent, 0.0f, 0.0f,
        0.0f, 0.0f, -A, -B,
        0.0f, 0.0f, 1.0f, 0.0f,
    };
}

...

float WidthOverHeight = ...;
mat4 ProjectionMatrix = Perspective4x4(DegreesToRadians(90.0f), WidthOverHeight, 50.0f, 0.1f);

这是我如何计算我的视图矩阵:

static mat4 Translate4x4(vec3 V)
{
    return
    {
        1.0f, 0.0f, 0.0f, V.X,
        0.0f, 1.0f, 0.0f, V.Y,
        0.0f, 0.0f, 1.0f, V.Z,
        0.0f, 0.0f, 0.0f, 1.0f
    };
}

...

mat4 ViewMatrix = Translate4x4(-CameraPosition);

这是我如何计算光标在世界空间中的位置:

mat4 ProjectionMatrix = ...;
mat4 ViewMatrix = ...;
    
vec2 CursorP = GetBilateralCursorPos(Input); // Values between -1 and 1

v4_f32 WorldSpacePNear = Inverse(ProjectionMatrix) * V4F32(CursorP, -1.0f, 1.0f);
WorldSpacePNear /= WorldSpacePNear.W;
WorldSpacePNear = Inverse(ViewMatrix) * WorldSpacePNear;
    
v4_f32 WorldSpacePFar = Inverse(ProjectionMatrix) * V4F32(CursorP, 1.0f, 1.0f);
WorldSpacePFar /= WorldSpacePFar.W;
WorldSpacePFar = Inverse(ViewMatrix) * WorldSpacePFar;
    
WorldSpacePFar.Z *= -1.0f;
WorldSpacePNear.Z *= -1.0f;

编辑:我也试过在最后除以w,但也不能正常工作。
这是我如何发送矩阵到OpenGL(传统):

// I send them transposed because my matrices are row-major
mat4 ProjectionMatrix = Transpose(...);
mat4 ViewMatrix = Transpose(...);

glMatrixMode(GL_PROJECTION);
glLoadMatrixf(ProjectionMatrix.E);
        
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(ViewMatrix.E);

生成的位置似乎没有考虑视图投影,因为相机位置的更改将使它们偏移,从而使它们不准确。
注:

  1. vec4,vec2,mat4是自定义的基于浮点数的数学类型。(它们是你所期望的)
    1.我知道传统的OpenGL已经过时了,事实上我很快就会切换到现代的OpenGL,我只是想让它工作。
jslywgbw

jslywgbw1#

我修正了计算游标位置的问题,如下所示:

mat4 ProjectionMatrix = ...;
mat4 ViewMatrix = ...;

// Z Distance from camera pos
float WorldDistanceFromCameraZ = 1.0f;

vec2 CursorP = GetBilateralCursorPos(Input); // Values between -1 and 1
    
vec4 ProbeZ = V4F32(World->Camera.P - WorldDistanceFromCameraZ*World->Camera.P.Z, 1.0f);
ProbeZ = (ProjectionMatrix*ViewMatrix) * ProbeZ;
    
vec4 ClipP = V4F32(CursorP.X*ProbeZ.W, CursorP.Y*ProbeZ.W, ProbeZ.Z, ProbeZ.W);
vec4 WorldP = Inverse(ProjectionMatrix*ViewMatrix) * ClipP;

相关问题