Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert screen space to world space coords in Bevy using Camera2dComponents?

Tags:

rust

bevy

Using Res<Events<CursorMoved>> I can get the mouse position change in screen space coordinates (zero in bottom-left corner), e.g.

#[derive(Default)]
struct State {
    cursor_moved_reader: EventReader<CursorMoved>,
}

fn set_mouse_pos(mut state: ResMut<State>, cursor_moved: Res<Events<CursorMoved>>) {
    for event in state.cursor_moved_reader.iter(&cursor_moved) {
        println!("cursor: {:?}", event.position);
    }
}

The question now is if I set SpriteComponents' transform.translation to the cursor position when using a camera from Camera2dComponents::default() a sprite with position 0, 0 is rendered in the center of the screen. What's the idiomatic way of converting between the screen space mouse coords and the camera world space coords?

like image 985
Jakub Arnold Avatar asked Nov 06 '20 11:11

Jakub Arnold


People also ask

How to transform from normalized device space to view device space?

Normalized device space is Cartesian coordinates system. Hency, if you want to transform from normalized device space to view space, you need to transform through the inverse projection matrix and divide the x, y, and z components through the w component. Since you are using GLM, I recommend using glm::unProject for the transformation.

What is the difference between clip space and normalized device space?

Clip space is a Homogeneous coordinate system. In order to transform from the clip space to normalized device space, you must do a Perspective divide. Normalized device space is Cartesian coordinates system.

How to get world coordinates of all vertices of a mesh?

If you need the world coordinates of all vertices, it's more efficient to use the transform () method: It will apply the transformation matrix to the mesh, so multiply the world matrix with all vertex coordinates. You may wonder about the change in orientation of a mesh object in viewport if you do the above.

How to get the global version of coordinates from local coordinates?

If you have your coords in a flat numpy.array from foreach_get ("co", coords), the following dot product of the world matrix with the local coordinates will get their their global version:


1 Answers

The previous answer seems to be on the right track, however the transformation is not fully implemented and actually overengineered. Stumbled on the same problem and figured that's what the camera transform is for! This works for me:

fn window_to_world(
    position: Vec2,
    window: &Window,
    camera: &Transform,
) -> Vec3 {

    // Center in screen space
    let norm = Vec3::new(
        position.x - window.width() / 2.,
        position.y - window.height() / 2.,
        0.,
    );

    // Apply camera transform
    *camera * norm

    // Alternatively:
    //camera.mul_vec3(norm)
}
like image 81
michalwa Avatar answered Sep 20 '22 12:09

michalwa