0
\$\begingroup\$

Heyho :)

I'm trying to convert world coordinates to screen coordinates. I have available: fov, screen width, screen height, camera position, camera angle and obviously the position of the object in world space.

This is what I tried:

glm::vec3 world_to_screen(glm::vec3 pos,
                          glm::vec3 cam_angle,
                          glm::vec3 cam_pos) {
    glm::mat4 projection = glm::perspective(
        glm::radians(FOV), (float)SCREEN_W / (float)SCREEN_H, NEAR, FAR);

    glm::mat4 model(1.0);

    model = glm::translate(model, cam_pos);

    model = glm::rotate(model, cam_angle.x, glm::vec3(1.0f, 0.0f, 0.0f));
    model = glm::rotate(model, cam_angle.y, glm::vec3(0.0f, 1.0f, 0.0f));
    model = glm::rotate(model, cam_angle.z, glm::vec3(0.0f, 0.0f, 1.0f));

    glm::mat4 view = glm::inverse(model);

    glm::mat4 modelview = view * model;

    return glm::project(pos, modelview, projection,
                        glm::vec4(0, 0, SCREEN_W, SCREEN_H));
}

However it is not working, the output screen coords are over 30000 (I don't have a 30k monitor...) and I'm not sure what I did wrong. There is a correlation though, sometimes the screen coords happen to be in my screen (I draw an indicator at the position to see if I did it right) and if the object moves the indicator also moves with (kinda) the same speed etc.

Help is very much appreciated :) Thanks a lot in advance!

\$\endgroup\$
0
\$\begingroup\$

Here is a working code, for your reference -- I got it at https://www.gamedev.net/forums/topic/708406-opengl-screen-to-world-coordinates-varying-eye-position-and-look_at-position/5432692/

void WorldToScreen (float screen[3], float world[3])
    {
        float s[4];
        s[0] = ( world[0] * MVP[0][0] ) + ( world[1] * MVP[1][0] ) + ( world[2] * MVP[2][0]) + MVP[3][0];
        s[1] = ( world[0] * MVP[0][1] ) + ( world[1] * MVP[1][1] ) + ( world[2] * MVP[2][1]) + MVP[3][1];
        s[2] = ( world[0] * MVP[0][2] ) + ( world[1] * MVP[1][2] ) + ( world[2] * MVP[2][2]) + MVP[3][2];
        s[3] = ( world[0] * MVP[0][3] ) + ( world[1] * MVP[1][3] ) + ( world[2] * MVP[2][3]) + MVP[3][3];   

        screen[0] = s[0] / s[3] * viewportWidth/2 + viewportWidth/2;
        screen[1] = s[1] / s[3] * viewportHeight/2 + viewportHeight/2;
        screen[2] = s[2] / s[3];
    }
    
    void ScreenToWorld (float world[3], float screen[3])
    {
        float s[3];
        s[0] = 2 * screen[0] / viewportWidth - 1;
        s[1] = 2 * screen[1] / viewportHeight - 1;
        s[2] = screen[2];

        float p[4];
        p[0] = ( s[0] * MVPinv[0][0] ) + ( s[1] * MVPinv[1][0] ) + ( s[2] * MVPinv[2][0]) + MVPinv[3][0];
        p[1] = ( s[0] * MVPinv[0][1] ) + ( s[1] * MVPinv[1][1] ) + ( s[2] * MVPinv[2][1]) + MVPinv[3][1];
        p[2] = ( s[0] * MVPinv[0][2] ) + ( s[1] * MVPinv[1][2] ) + ( s[2] * MVPinv[2][2]) + MVPinv[3][2];
        p[3] = ( s[0] * MVPinv[0][3] ) + ( s[1] * MVPinv[1][3] ) + ( s[2] * MVPinv[2][3]) + MVPinv[3][3];   

        float w = 1 / p[3];
        world[0] = p[0] * w;
        world[1] = p[1] * w;
        world[2] = p[2] * w;
    }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.