-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Building on #1799 : Add a function for computing a world point from a screen point #4177
Changes from all commits
6b6df6d
03a9f7e
3a243f6
842732a
3fb86b4
64e0618
8833508
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -192,6 +192,18 @@ impl CubemapFrusta { | |
} | ||
} | ||
|
||
#[derive(Clone, Copy, Debug, Default)] | ||
pub struct Line { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should provide the result as a pair of Vec3's, and not a
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have very similar code to what's here, and I use a pub struct Ray<V> {
pub origin: V,
pub direction: V,
} A ray is useful, because the math is simpler for intersections, and the equation is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Shapes RFC also has rays. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed a ray is more apt here. My opinion is we defer adding primitives to the RFC impl, especially considering we don't have cart's final blessing. |
||
pub point: Vec3, | ||
pub direction: Vec3, | ||
} | ||
|
||
impl Line { | ||
pub fn from_point_direction(point: Vec3, direction: Vec3) -> Self { | ||
Self { point, direction } | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use bevy::{prelude::*, render::camera::Camera}; | ||
|
||
fn main() { | ||
App::new() | ||
.add_plugins(DefaultPlugins) | ||
.add_startup_system(setup) | ||
.add_system(follow) | ||
.run(); | ||
} | ||
|
||
#[derive(Component)] | ||
struct Follow; | ||
|
||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) { | ||
let texture_handle = asset_server.load("branding/icon.png"); | ||
commands.spawn_bundle(OrthographicCameraBundle::new_2d()); | ||
commands | ||
.spawn_bundle(SpriteBundle { | ||
texture: texture_handle, | ||
..Default::default() | ||
}) | ||
.insert(Follow); | ||
} | ||
|
||
fn follow( | ||
mut q: Query<&mut Transform, With<Follow>>, | ||
q_camera: Query<(&Camera, &GlobalTransform)>, | ||
windows: Res<Windows>, | ||
images: Res<Assets<Image>>, | ||
mut evr_cursor: EventReader<CursorMoved>, | ||
) { | ||
let (camera, camera_transform) = q_camera.single(); | ||
if let Some(cursor) = evr_cursor.iter().next() { | ||
for mut transform in q.iter_mut() { | ||
let point: Option<Vec3> = | ||
camera.screen_to_point_2d(cursor.position, &windows, &images, camera_transform); | ||
println!("Point {:?}", point); | ||
if let Some(point) = point { | ||
transform.translation = point; | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
use bevy::{prelude::*, render::camera::Camera, render::primitives::Plane}; | ||
|
||
fn main() { | ||
App::new() | ||
.insert_resource(Msaa { samples: 4 }) | ||
.add_plugins(DefaultPlugins) | ||
.add_startup_system(setup) | ||
.add_system(follow) | ||
.run(); | ||
} | ||
|
||
#[derive(Component)] | ||
struct Follow; | ||
|
||
/// set up a simple 3D scene | ||
fn setup( | ||
mut commands: Commands, | ||
mut meshes: ResMut<Assets<Mesh>>, | ||
mut materials: ResMut<Assets<StandardMaterial>>, | ||
) { | ||
// plane | ||
commands.spawn_bundle(PbrBundle { | ||
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })), | ||
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), | ||
..Default::default() | ||
}); | ||
// cube | ||
commands | ||
.spawn_bundle(PbrBundle { | ||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), | ||
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()), | ||
transform: Transform::from_xyz(0.0, 0.5, 0.0), | ||
..Default::default() | ||
}) | ||
.insert(Follow); | ||
// light | ||
commands.spawn_bundle(PointLightBundle { | ||
transform: Transform::from_xyz(4.0, 8.0, 4.0), | ||
..Default::default() | ||
}); | ||
// camera | ||
commands.spawn_bundle(PerspectiveCameraBundle { | ||
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), | ||
..Default::default() | ||
}); | ||
} | ||
|
||
fn follow( | ||
mut q: Query<&mut Transform, With<Follow>>, | ||
q_camera: Query<(&Camera, &GlobalTransform)>, | ||
windows: Res<Windows>, | ||
images: Res<Assets<Image>>, | ||
mut evr_cursor: EventReader<CursorMoved>, | ||
) { | ||
// Assumes there is at least one camera | ||
let (camera, camera_transform) = q_camera.iter().next().unwrap(); | ||
if let Some(cursor) = evr_cursor.iter().next() { | ||
for mut transform in q.iter_mut() { | ||
let point: Option<Vec3> = camera.screen_to_point_on_plane( | ||
cursor.position, | ||
Plane::new(Vec4::new(0., 1., 0., 1.)), | ||
&windows, | ||
&images, | ||
camera_transform, | ||
); | ||
if let Some(point) = point { | ||
transform.translation = point + Vec3::new(0., 0.5, 0.); | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this projecting to infinity, since the far plane is at -Infinity Z for reversed-Z perspective projection?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just noticed this is taken directly from an old version of
bevy_mod_raycast
, which does not work with the new projections for the reason you stated.Here is the current version of that function that works with bevy main: https://github.com/aevyrie/bevy_mod_raycast/blob/main/src/primitives.rs#L180-L217
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, the code "taken" is from a repo with an MIT license. I could re-license that repo as MIT/Apache if I get permission from contributors, but I'm not very familiar with licensing laws. The math here is well understood and fairly trivial, the only issue I can see is there was an obvious copy-paste.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A simpler solution is to use z = 1.0 for the near plane and z = 0.5 for half-way to the far plane (just kidding, it works though.)