world coords to screen space (#1258)
Add Camera::world_to_screen to convert world coordinates to screen space
This commit is contained in:
parent
f15d62c0f1
commit
18e4fa8cdf
@ -1,8 +1,9 @@
|
|||||||
use super::CameraProjection;
|
use super::CameraProjection;
|
||||||
use bevy_app::prelude::EventReader;
|
use bevy_app::prelude::EventReader;
|
||||||
use bevy_ecs::{Added, Component, Entity, Query, QuerySet, Res};
|
use bevy_ecs::{Added, Component, Entity, Query, QuerySet, Res};
|
||||||
use bevy_math::Mat4;
|
use bevy_math::{Mat4, Vec2, Vec3};
|
||||||
use bevy_reflect::{Reflect, ReflectComponent};
|
use bevy_reflect::{Reflect, ReflectComponent};
|
||||||
|
use bevy_transform::components::GlobalTransform;
|
||||||
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
|
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
|
||||||
|
|
||||||
#[derive(Default, Debug, Reflect)]
|
#[derive(Default, Debug, Reflect)]
|
||||||
@ -28,6 +29,30 @@ impl Default for DepthCalculation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Camera {
|
||||||
|
/// Given a position in world space, use the camera to compute the screen space coordinates.
|
||||||
|
pub fn world_to_screen(
|
||||||
|
&self,
|
||||||
|
windows: &Windows,
|
||||||
|
camera_transform: &GlobalTransform,
|
||||||
|
world_position: Vec3,
|
||||||
|
) -> Option<Vec2> {
|
||||||
|
let window = windows.get(self.window)?;
|
||||||
|
let window_size = Vec2::new(window.width(), window.height());
|
||||||
|
// Build a transform to convert from world to NDC using camera data
|
||||||
|
let world_to_ndc: Mat4 =
|
||||||
|
self.projection_matrix * camera_transform.compute_matrix().inverse();
|
||||||
|
let ndc_space_coords: Vec3 = world_to_ndc.transform_point3(world_position);
|
||||||
|
// NDC z-values outside of 0 < z < 1 are behind the camera and are thus not in screen space
|
||||||
|
if ndc_space_coords.z < 0.0 || ndc_space_coords.z > 1.0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
// Once in NDC space, we can discard the z element and rescale x/y to fit the screen
|
||||||
|
let screen_space_coords = (ndc_space_coords.truncate() + Vec2::one()) / 2.0 * window_size;
|
||||||
|
Some(screen_space_coords)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn camera_system<T: CameraProjection + Component>(
|
pub fn camera_system<T: CameraProjection + Component>(
|
||||||
mut window_resized_events: EventReader<WindowResized>,
|
mut window_resized_events: EventReader<WindowResized>,
|
||||||
mut window_created_events: EventReader<WindowCreated>,
|
mut window_created_events: EventReader<WindowCreated>,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user