From 0f02b01f3c814ec32d07bcd99c1469a1af181dbb Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Fri, 2 Oct 2020 12:44:16 +0200 Subject: [PATCH 01/12] first draft and example --- crates/bevy_physics/Cargo.toml | 23 ++++++++ crates/bevy_physics/src/d3/geometry.rs | 57 +++++++++++++++++++ crates/bevy_physics/src/d3/intersectors.rs | 64 ++++++++++++++++++++++ crates/bevy_physics/src/d3/mod.rs | 7 +++ crates/bevy_physics/src/d3/ray.rs | 59 ++++++++++++++++++++ crates/bevy_physics/src/lib.rs | 1 + 6 files changed, 211 insertions(+) create mode 100644 crates/bevy_physics/Cargo.toml create mode 100644 crates/bevy_physics/src/d3/geometry.rs create mode 100644 crates/bevy_physics/src/d3/intersectors.rs create mode 100644 crates/bevy_physics/src/d3/mod.rs create mode 100644 crates/bevy_physics/src/d3/ray.rs create mode 100644 crates/bevy_physics/src/lib.rs diff --git a/crates/bevy_physics/Cargo.toml b/crates/bevy_physics/Cargo.toml new file mode 100644 index 0000000000000..0d896ae9abc51 --- /dev/null +++ b/crates/bevy_physics/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "bevy_physics" +version = "0.2.1" +edition = "2018" +authors = [ + "Bevy Contributors ", + "Carter Anderson ", +] +description = "Provides physics functionality for Bevy Engine" +homepage = "https://bevyengine.org" +repository = "https://github.com/bevyengine/bevy" +license = "MIT" +keywords = ["bevy"] + +[dependencies] +# bevy +bevy_transform = { path = "../bevy_transform", version = "0.2.1" } +bevy_render = { path = "../bevy_render", version = "0.2.1" } +bevy_window = { path = "../bevy_window", version = "0.2.1" } + +# linear algebra +glam = { version = "0.9.4", features = ["serde"] } + diff --git a/crates/bevy_physics/src/d3/geometry.rs b/crates/bevy_physics/src/d3/geometry.rs new file mode 100644 index 0000000000000..772d2df04c5b6 --- /dev/null +++ b/crates/bevy_physics/src/d3/geometry.rs @@ -0,0 +1,57 @@ +use glam::Vec3; + +pub struct Plane { + center: Vec3, + normal: Vec3, +} + +impl Plane { + pub fn new(center: Vec3, normal: Vec3) -> Self { + normal.normalize(); + Self { center, normal } + } + + pub fn center(&self) -> &Vec3 { + &self.center + } + + pub fn center_mut(&mut self) -> &mut Vec3 { + &mut self.center + } + + pub fn normal(&self) -> &Vec3 { + &self.normal + } + + pub fn set_normal(&mut self, normal: Vec3) { + normal.normalize(); + self.normal = normal; + } +} + +impl Default for Plane { + fn default() -> Self { + Plane { + center: Vec3::zero(), + normal: Vec3::unit_y(), + } + } +} + +pub struct Sphere { + pub center: Vec3, + pub radius: f32, +} + +impl Default for Sphere { + fn default() -> Self { + Sphere { + center: Vec3::zero(), + radius: 1.0, + } + } +} + +pub struct Triangle { + pub vertices: [Vec3; 3], +} diff --git a/crates/bevy_physics/src/d3/intersectors.rs b/crates/bevy_physics/src/d3/intersectors.rs new file mode 100644 index 0000000000000..04382db74a118 --- /dev/null +++ b/crates/bevy_physics/src/d3/intersectors.rs @@ -0,0 +1,64 @@ +use super::{geometry::*, ray::*}; +use glam::Vec3; + +pub struct RayHit { + t: f32, + point: Vec3, +} + +impl RayHit { + pub fn new(t: f32, point: Vec3) -> Self { + Self { t, point } + } + + pub fn t(&self) -> &f32 { + &self.t + } + + pub fn point(&self) -> &Vec3 { + &self.point + } +} + +pub trait RayIntersector { + fn intersect_ray(&self, ray: &Ray) -> Option; +} + +impl RayIntersector for Plane { + fn intersect_ray(&self, ray: &Ray) -> Option { + let d = self.normal().dot(*ray.direction()); + if d.abs() > f32::EPSILON { + let t = (*self.center() - *ray.origin()).dot(*self.normal()) / d; + if t > 0.0 { + return Some(RayHit::new(t, *ray.origin() + *ray.direction() * t)); + } + } + + None + } +} + +impl RayIntersector for Sphere { + fn intersect_ray(&self, ray: &Ray) -> Option { + let oc = *ray.origin() - self.center; + let a = ray.direction().length_squared(); + let b = 2.0 * oc.dot(*ray.direction()); + let c = oc.length_squared() - self.radius.powi(2); + + let d = b.powi(2) - 4.0 * a * c; + + if d < 0.0 { + None + } else { + let t = (-b - d.sqrt()) / (2.0 * a); + + Some(RayHit::new(t, *ray.origin() + *ray.direction() * t)) + } + } +} + +impl RayIntersector for Triangle { + fn intersect_ray(&self, _ray: &Ray) -> Option { + unimplemented!() + } +} diff --git a/crates/bevy_physics/src/d3/mod.rs b/crates/bevy_physics/src/d3/mod.rs new file mode 100644 index 0000000000000..abac655758f5e --- /dev/null +++ b/crates/bevy_physics/src/d3/mod.rs @@ -0,0 +1,7 @@ +pub mod geometry; +pub mod intersectors; +pub mod ray; + +pub mod prelude { + pub use super::{geometry::*, intersectors::*, ray::*}; +} diff --git a/crates/bevy_physics/src/d3/ray.rs b/crates/bevy_physics/src/d3/ray.rs new file mode 100644 index 0000000000000..6b19a6ad3c3ce --- /dev/null +++ b/crates/bevy_physics/src/d3/ray.rs @@ -0,0 +1,59 @@ +use bevy_render::camera::Camera; +use bevy_transform::components::GlobalTransform; +use bevy_window::Window; +use glam::{Vec2, Vec3}; + +pub struct Ray { + origin: Vec3, + direction: Vec3, +} + +impl Ray { + pub fn new(origin: Vec3, direction: Vec3) -> Self { + direction.normalize(); + Self { origin, direction } + } + + pub fn from_mouse_position( + mouse_position: &Vec2, + window: &Window, + camera: &Camera, + camera_transform: &GlobalTransform, + ) -> Self { + if window.id != camera.window { + panic!("Generating Ray from Camera with wrong Window"); + } + + let x = 2.0 * (mouse_position.x() / window.width as f32) - 1.0; + let y = 2.0 * (mouse_position.y() / window.height as f32) - 1.0; + + let camera_inverse_matrix = *camera_transform.value() * camera.projection_matrix.inverse(); + let near = camera_inverse_matrix * Vec3::new(x, y, 0.0).extend(1.0); + let far = camera_inverse_matrix * Vec3::new(x, y, 1.0).extend(1.0); + + let near = near.truncate() / near.w(); + let far = far.truncate() / far.w(); + + let direction: Vec3 = (far - near).into(); + let origin: Vec3 = near.into(); + + return Self { origin, direction }; + } + + pub fn origin(&self) -> &Vec3 { + &self.origin + } + + pub fn origin_mut(&mut self) -> &mut Vec3 { + &mut self.origin + } + + pub fn direction(&self) -> &Vec3 { + &self.direction + } + + pub fn set_direction(&mut self, direction: Vec3) { + direction.normalize(); + self.direction = direction; + } +} diff --git a/crates/bevy_physics/src/lib.rs b/crates/bevy_physics/src/lib.rs new file mode 100644 index 0000000000000..102a0ab4bc6d6 --- /dev/null +++ b/crates/bevy_physics/src/lib.rs @@ -0,0 +1 @@ +pub mod d3; From dd99c79a635d68fa0f762b17df724a46c2bfa951 Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Fri, 2 Oct 2020 12:45:43 +0200 Subject: [PATCH 02/12] forgot to add those --- Cargo.toml | 5 ++ examples/physics/raycast.rs | 154 ++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 160 insertions(+) create mode 100644 examples/physics/raycast.rs diff --git a/Cargo.toml b/Cargo.toml index 9d55b8471fc62..3454585dc7d2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ bevy_diagnostic = { path = "crates/bevy_diagnostic", version = "0.2.1" } bevy_ecs = { path = "crates/bevy_ecs", version = "0.2.1" } bevy_input = { path = "crates/bevy_input", version = "0.2.1" } bevy_math = { path = "crates/bevy_math", version = "0.2.1" } +bevy_physics = { path = "crates/bevy_physics", version = "0.2.1" } bevy_property = { path = "crates/bevy_property", version = "0.2.1" } bevy_scene = { path = "crates/bevy_scene", version = "0.2.1" } bevy_transform = { path = "crates/bevy_transform", version = "0.2.1" } @@ -138,6 +139,10 @@ path = "examples/3d/texture.rs" name = "z_sort_debug" path = "examples/3d/z_sort_debug.rs" +[[example]] +name = "raycast" +path = "examples/physics/raycast.rs" + [[example]] name = "empty_defaults" path = "examples/app/empty_defaults.rs" diff --git a/examples/physics/raycast.rs b/examples/physics/raycast.rs new file mode 100644 index 0000000000000..2f4cc4864cb58 --- /dev/null +++ b/examples/physics/raycast.rs @@ -0,0 +1,154 @@ +use bevy::{ + input::{keyboard::ElementState, mouse::MouseButtonInput}, + physics::d3::prelude::*, + prelude::*, + render::camera::Camera, +}; + +fn main() { + App::build() + .add_resource(Msaa { samples: 4 }) + .add_default_plugins() + .add_startup_system(setup.system()) + .add_system(raycast.system()) + .add_system(move_camera.system()) + .run(); +} + +fn setup( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + commands + .spawn(PbrComponents { + mesh: meshes.add(Mesh::from(shape::Plane { size: 10.0 })), + material: materials.add(Color::rgb(0.1, 0.2, 0.1).into()), + ..Default::default() + }) + .spawn(PbrComponents { + mesh: meshes.add(Mesh::from(shape::Icosphere { + subdivisions: 4, + radius: 0.5, + })), + material: materials.add(Color::rgb(0.1, 0.4, 0.8).into()), + transform: Transform::from_translation(Vec3::new(1.5, 1.5, 0.0)), + ..Default::default() + }) + .spawn(LightComponents { + transform: Transform::from_translation(Vec3::new(4.0, 8.0, 4.0)), + ..Default::default() + }) + .spawn(Camera3dComponents { + transform: Transform::new(Mat4::face_toward( + Vec3::new(-3.0, 5.0, 8.0), + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 1.0, 0.0), + )), + ..Default::default() + }) + .insert_resource(MouseState::default()); +} + +#[derive(Default)] +struct MouseState { + mouse_button_event_reader: EventReader, + cursor_moved_event_reader: EventReader, + cursor_position: Vec2, +} + +fn raycast( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, + mut mouse_state: ResMut, + mouse_button_input_events: Res>, + cursor_moved_events: Res>, + windows: Res, + mut cameras: Query<(&Camera, &GlobalTransform)>, +) { + for event in mouse_state + .cursor_moved_event_reader + .iter(&cursor_moved_events) + { + mouse_state.cursor_position = event.position; + } + + for event in mouse_state + .mouse_button_event_reader + .iter(&mouse_button_input_events) + { + if event.button == MouseButton::Left && event.state == ElementState::Pressed { + for (camera, global_transform) in &mut cameras.iter() { + let window = windows.get(camera.window).unwrap(); + + let ray = Ray::from_mouse_position( + &mouse_state.cursor_position, + window, + camera, + global_transform, + ); + + let plane_hit = Plane::new(Vec3::zero(), Vec3::unit_y()).intersect_ray(&ray); + let sphere_hit = Sphere { + center: Vec3::new(1.5, 1.5, 0.0), + radius: 0.5, + } + .intersect_ray(&ray); + + let hit = if let Some(plane_hit) = plane_hit { + if let Some(sphere_hit) = sphere_hit { + if plane_hit.t() < sphere_hit.t() { + Some(plane_hit) + } else { + Some(sphere_hit) + } + } else { + Some(plane_hit) + } + } else if let Some(sphere_hit) = sphere_hit { + Some(sphere_hit) + } else { + None + }; + + if let Some(hit) = hit { + commands.spawn(PbrComponents { + mesh: meshes.add(Mesh::from(shape::Icosphere { + subdivisions: 3, + radius: 0.05, + })), + material: materials.add(Color::RED.into()), + transform: Transform::from_translation(*hit.point()), + ..Default::default() + }); + } + } + } + } +} + +fn move_camera(keyboard_input: Res>, mut cameras: Query<(&mut Transform, &Camera)>) { + let speed = 0.1; + + let translation = Vec3::unit_x() + * speed + * if keyboard_input.pressed(KeyCode::A) { + -1.0 + } else if keyboard_input.pressed(KeyCode::D) { + 1.0 + } else { + 0.0 + }; + + for (mut camera_transform, _) in &mut cameras.iter() { + let rotation = camera_transform.rotation(); + camera_transform.translate(rotation * translation); + let position = camera_transform.translation(); + camera_transform.set_rotation(Quat::from_rotation_mat4(&Mat4::face_toward( + position, + Vec3::zero(), + Vec3::unit_y(), + ))); + } +} diff --git a/src/lib.rs b/src/lib.rs index 35c9ae3b75dc6..06a22621a8a2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,6 +48,7 @@ pub use bevy_diagnostic as diagnostic; pub use bevy_ecs as ecs; pub use bevy_input as input; pub use bevy_math as math; +pub use bevy_physics as physics; pub use bevy_property as property; pub use bevy_scene as scene; pub use bevy_tasks as tasks; From 1f31d004cb50479613d586136b82a1da4e4dec88 Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Fri, 2 Oct 2020 13:17:32 +0200 Subject: [PATCH 03/12] added triangle intersector --- crates/bevy_physics/src/d3/geometry.rs | 4 +-- crates/bevy_physics/src/d3/intersectors.rs | 34 ++++++++++++++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/crates/bevy_physics/src/d3/geometry.rs b/crates/bevy_physics/src/d3/geometry.rs index 772d2df04c5b6..8f1cf3d13f264 100644 --- a/crates/bevy_physics/src/d3/geometry.rs +++ b/crates/bevy_physics/src/d3/geometry.rs @@ -52,6 +52,4 @@ impl Default for Sphere { } } -pub struct Triangle { - pub vertices: [Vec3; 3], -} +pub struct Triangle(pub Vec3, pub Vec3, pub Vec3); diff --git a/crates/bevy_physics/src/d3/intersectors.rs b/crates/bevy_physics/src/d3/intersectors.rs index 04382db74a118..ab5e317cc28f0 100644 --- a/crates/bevy_physics/src/d3/intersectors.rs +++ b/crates/bevy_physics/src/d3/intersectors.rs @@ -58,7 +58,37 @@ impl RayIntersector for Sphere { } impl RayIntersector for Triangle { - fn intersect_ray(&self, _ray: &Ray) -> Option { - unimplemented!() + // using the Moeller-Trumbore intersection algorithm + fn intersect_ray(&self, ray: &Ray) -> Option { + let edges = (self.1 - self.0, self.2 - self.0); + let h = ray.direction().cross(edges.1); + let a = edges.0.dot(h); + + if a > -f32::EPSILON && a < f32::EPSILON { + return None; + } + + let f = 1.0 / a; + let s = *ray.origin() - self.0; + let u = f * s.dot(h); + + if u < 0.0 || u > 1.0 { + return None; + } + + let q = s.cross(edges.0); + let v = f * ray.direction().dot(q); + + if v < 0.0 || u + v > 1.0 { + return None; + } + + let t = f * edges.1.dot(q); + + if t > f32::EPSILON { + Some(RayHit::new(t, *ray.origin() + *ray.direction() * t)) + } else { + None + } } } From be23d74f47f28c3c95908a0052efc5fb00d91edb Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Fri, 4 Dec 2020 11:31:55 +0100 Subject: [PATCH 04/12] merge upstream --- crates/bevy_internal/Cargo.toml | 1 + crates/bevy_internal/src/lib.rs | 5 ++++ crates/bevy_physics/Cargo.toml | 10 +++---- crates/bevy_physics/src/d3/ray.rs | 13 +++++---- examples/physics/raycast.rs | 46 +++++++++++++------------------ 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 4475b06e80eff..1df3faf7bd4bb 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -46,6 +46,7 @@ bevy_input = { path = "../bevy_input", version = "0.3.0" } bevy_log = { path = "../bevy_log", version = "0.3.0" } bevy_math = { path = "../bevy_math", version = "0.3.0" } bevy_reflect = { path = "../bevy_reflect", version = "0.3.0", features = ["bevy"] } +bevy_physics = { path = "../bevy_physics", version = "0.3.0" } bevy_scene = { path = "../bevy_scene", version = "0.3.0" } bevy_transform = { path = "../bevy_transform", version = "0.3.0" } bevy_utils = { path = "../bevy_utils", version = "0.3.0" } diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index 4f2450bfa66d1..2d415d3dee805 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -44,6 +44,11 @@ pub mod math { pub use bevy_math::*; } +pub mod physics { + //! colliders and raycasting + pub use bevy_physics::*; +} + pub mod reflect { // TODO: remove these renames once TypeRegistryArc is no longer required //! Type reflection used for dynamically interacting with rust types. diff --git a/crates/bevy_physics/Cargo.toml b/crates/bevy_physics/Cargo.toml index 0d896ae9abc51..592c68200d43d 100644 --- a/crates/bevy_physics/Cargo.toml +++ b/crates/bevy_physics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bevy_physics" -version = "0.2.1" +version = "0.3.0" edition = "2018" authors = [ "Bevy Contributors ", @@ -14,10 +14,10 @@ keywords = ["bevy"] [dependencies] # bevy -bevy_transform = { path = "../bevy_transform", version = "0.2.1" } -bevy_render = { path = "../bevy_render", version = "0.2.1" } -bevy_window = { path = "../bevy_window", version = "0.2.1" } +bevy_transform = { path = "../bevy_transform", version = "0.3.0" } +bevy_render = { path = "../bevy_render", version = "0.3.0" } +bevy_window = { path = "../bevy_window", version = "0.3.0" } # linear algebra -glam = { version = "0.9.4", features = ["serde"] } +glam = { version = "0.11.2", features = ["serde"] } diff --git a/crates/bevy_physics/src/d3/ray.rs b/crates/bevy_physics/src/d3/ray.rs index 6b19a6ad3c3ce..a4e5115c1fd0d 100644 --- a/crates/bevy_physics/src/d3/ray.rs +++ b/crates/bevy_physics/src/d3/ray.rs @@ -20,19 +20,20 @@ impl Ray { camera: &Camera, camera_transform: &GlobalTransform, ) -> Self { - if window.id != camera.window { + if window.id() != camera.window { panic!("Generating Ray from Camera with wrong Window"); } - let x = 2.0 * (mouse_position.x() / window.width as f32) - 1.0; - let y = 2.0 * (mouse_position.y() / window.height as f32) - 1.0; + let x = 2.0 * (mouse_position.x / window.width() as f32) - 1.0; + let y = 2.0 * (mouse_position.y / window.height() as f32) - 1.0; - let camera_inverse_matrix = *camera_transform.value() * camera.projection_matrix.inverse(); + let camera_inverse_matrix = + camera_transform.compute_matrix() * camera.projection_matrix.inverse(); let near = camera_inverse_matrix * Vec3::new(x, y, 0.0).extend(1.0); let far = camera_inverse_matrix * Vec3::new(x, y, 1.0).extend(1.0); - let near = near.truncate() / near.w(); - let far = far.truncate() / far.w(); + let near = near.truncate() / near.w; + let far = far.truncate() / far.w; let direction: Vec3 = (far - near).into(); let origin: Vec3 = near.into(); diff --git a/examples/physics/raycast.rs b/examples/physics/raycast.rs index 2f4cc4864cb58..37e7b702c3e9d 100644 --- a/examples/physics/raycast.rs +++ b/examples/physics/raycast.rs @@ -1,5 +1,5 @@ use bevy::{ - input::{keyboard::ElementState, mouse::MouseButtonInput}, + input::{mouse::MouseButtonInput, ElementState}, physics::d3::prelude::*, prelude::*, render::camera::Camera, @@ -8,25 +8,25 @@ use bevy::{ fn main() { App::build() .add_resource(Msaa { samples: 4 }) - .add_default_plugins() - .add_startup_system(setup.system()) - .add_system(raycast.system()) + .add_plugins(DefaultPlugins) + .add_startup_system(setup) + .add_system(raycast) .add_system(move_camera.system()) .run(); } fn setup( - mut commands: Commands, + commands: &mut Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { commands - .spawn(PbrComponents { + .spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::Plane { size: 10.0 })), material: materials.add(Color::rgb(0.1, 0.2, 0.1).into()), ..Default::default() }) - .spawn(PbrComponents { + .spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::Icosphere { subdivisions: 4, radius: 0.5, @@ -35,16 +35,13 @@ fn setup( transform: Transform::from_translation(Vec3::new(1.5, 1.5, 0.0)), ..Default::default() }) - .spawn(LightComponents { + .spawn(LightBundle { transform: Transform::from_translation(Vec3::new(4.0, 8.0, 4.0)), ..Default::default() }) - .spawn(Camera3dComponents { - transform: Transform::new(Mat4::face_toward( - Vec3::new(-3.0, 5.0, 8.0), - Vec3::new(0.0, 0.0, 0.0), - Vec3::new(0.0, 1.0, 0.0), - )), + .spawn(Camera3dBundle { + transform: Transform::from_translation(Vec3::new(-3.0, 5.0, 8.0)) + .looking_at(Vec3::zero(), Vec3::unit_y()), ..Default::default() }) .insert_resource(MouseState::default()); @@ -58,14 +55,14 @@ struct MouseState { } fn raycast( - mut commands: Commands, + commands: &mut Commands, mut meshes: ResMut>, mut materials: ResMut>, mut mouse_state: ResMut, mouse_button_input_events: Res>, cursor_moved_events: Res>, windows: Res, - mut cameras: Query<(&Camera, &GlobalTransform)>, + cameras: Query<(&Camera, &GlobalTransform)>, ) { for event in mouse_state .cursor_moved_event_reader @@ -79,7 +76,7 @@ fn raycast( .iter(&mouse_button_input_events) { if event.button == MouseButton::Left && event.state == ElementState::Pressed { - for (camera, global_transform) in &mut cameras.iter() { + for (camera, global_transform) in cameras.iter() { let window = windows.get(camera.window).unwrap(); let ray = Ray::from_mouse_position( @@ -113,7 +110,7 @@ fn raycast( }; if let Some(hit) = hit { - commands.spawn(PbrComponents { + commands.spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::Icosphere { subdivisions: 3, radius: 0.05, @@ -141,14 +138,9 @@ fn move_camera(keyboard_input: Res>, mut cameras: Query<(&mut Tra 0.0 }; - for (mut camera_transform, _) in &mut cameras.iter() { - let rotation = camera_transform.rotation(); - camera_transform.translate(rotation * translation); - let position = camera_transform.translation(); - camera_transform.set_rotation(Quat::from_rotation_mat4(&Mat4::face_toward( - position, - Vec3::zero(), - Vec3::unit_y(), - ))); + for (mut camera_transform, _) in cameras.iter_mut() { + let rotation = camera_transform.rotation; + camera_transform.translation += rotation * translation; + camera_transform.look_at(Vec3::zero(), Vec3::unit_y()); } } From 5fb710aa5306eaef7d11c569ba6a48594f8d9ac3 Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Fri, 4 Dec 2020 11:33:27 +0100 Subject: [PATCH 05/12] added from_window(..) --- crates/bevy_physics/src/d3/ray.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/bevy_physics/src/d3/ray.rs b/crates/bevy_physics/src/d3/ray.rs index a4e5115c1fd0d..2a63ded544d7b 100644 --- a/crates/bevy_physics/src/d3/ray.rs +++ b/crates/bevy_physics/src/d3/ray.rs @@ -14,6 +14,14 @@ impl Ray { Self { origin, direction } } + pub fn from_window( + window: &Window, + camera: &Camera, + camera_transform: &GlobalTransform, + ) -> Self { + Self::from_mouse_position(window.cursor_position(), camera, camera_transform) + } + pub fn from_mouse_position( mouse_position: &Vec2, window: &Window, From 29f5d5088dd447634e4c942641de1ce1192f1c28 Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Fri, 4 Dec 2020 11:35:39 +0100 Subject: [PATCH 06/12] fixed from_window(..) --- crates/bevy_physics/src/d3/ray.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/bevy_physics/src/d3/ray.rs b/crates/bevy_physics/src/d3/ray.rs index 2a63ded544d7b..4aebe6dd290c9 100644 --- a/crates/bevy_physics/src/d3/ray.rs +++ b/crates/bevy_physics/src/d3/ray.rs @@ -19,7 +19,12 @@ impl Ray { camera: &Camera, camera_transform: &GlobalTransform, ) -> Self { - Self::from_mouse_position(window.cursor_position(), camera, camera_transform) + Self::from_mouse_position( + &window.cursor_position().unwrap(), + window, + camera, + camera_transform, + ) } pub fn from_mouse_position( From 0b93d4b0ff37241cfc026daa565fce327fd63b73 Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Wed, 9 Dec 2020 10:32:34 +0100 Subject: [PATCH 07/12] renamed HitPoint.t to distance --- crates/bevy_physics/src/d3/intersectors.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_physics/src/d3/intersectors.rs b/crates/bevy_physics/src/d3/intersectors.rs index ab5e317cc28f0..4e271202161de 100644 --- a/crates/bevy_physics/src/d3/intersectors.rs +++ b/crates/bevy_physics/src/d3/intersectors.rs @@ -2,17 +2,17 @@ use super::{geometry::*, ray::*}; use glam::Vec3; pub struct RayHit { - t: f32, + distance: f32, point: Vec3, } impl RayHit { - pub fn new(t: f32, point: Vec3) -> Self { - Self { t, point } + pub fn new(distance: f32, point: Vec3) -> Self { + Self { distance, point } } - pub fn t(&self) -> &f32 { - &self.t + pub fn distance(&self) -> &f32 { + &self.distance } pub fn point(&self) -> &Vec3 { From bfe56907cb6a2843e95c9e256f4890b46b846567 Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Wed, 9 Dec 2020 10:35:16 +0100 Subject: [PATCH 08/12] added meaningful variable names --- crates/bevy_physics/src/d3/intersectors.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/bevy_physics/src/d3/intersectors.rs b/crates/bevy_physics/src/d3/intersectors.rs index 4e271202161de..40411aa099f0f 100644 --- a/crates/bevy_physics/src/d3/intersectors.rs +++ b/crates/bevy_physics/src/d3/intersectors.rs @@ -26,11 +26,14 @@ pub trait RayIntersector { impl RayIntersector for Plane { fn intersect_ray(&self, ray: &Ray) -> Option { - let d = self.normal().dot(*ray.direction()); - if d.abs() > f32::EPSILON { - let t = (*self.center() - *ray.origin()).dot(*self.normal()) / d; - if t > 0.0 { - return Some(RayHit::new(t, *ray.origin() + *ray.direction() * t)); + let denominator = self.normal().dot(*ray.direction()); + if denominator.abs() > f32::EPSILON { + let distance = (*self.center() - *ray.origin()).dot(*self.normal()) / denominator; + if distance > 0.0 { + return Some(RayHit::new( + distance, + *ray.origin() + *ray.direction() * distance, + )); } } From f771a90a3ea9691330c683ed86301615246a4f33 Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Wed, 9 Dec 2020 10:44:30 +0100 Subject: [PATCH 09/12] adjusted RayHit variable names --- examples/physics/raycast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/physics/raycast.rs b/examples/physics/raycast.rs index 37e7b702c3e9d..33b50c3c3b55b 100644 --- a/examples/physics/raycast.rs +++ b/examples/physics/raycast.rs @@ -95,7 +95,7 @@ fn raycast( let hit = if let Some(plane_hit) = plane_hit { if let Some(sphere_hit) = sphere_hit { - if plane_hit.t() < sphere_hit.t() { + if plane_hit.distance() < sphere_hit.distance() { Some(plane_hit) } else { Some(sphere_hit) From 22e62f71e1315e3c9ae27fa1fccf3b9458b3843d Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Wed, 9 Dec 2020 10:48:03 +0100 Subject: [PATCH 10/12] used spaces instead of tabs --- crates/bevy_internal/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index 2d415d3dee805..34a971cc4d799 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -45,7 +45,7 @@ pub mod math { } pub mod physics { - //! colliders and raycasting + //! colliders and raycasting pub use bevy_physics::*; } From 3a0b37619fbbcbcb165b50fd180133d0e85609da Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Wed, 9 Dec 2020 11:43:26 +0100 Subject: [PATCH 11/12] changes for clippy --- crates/bevy_physics/src/d3/intersectors.rs | 18 +++++++++++++----- crates/bevy_physics/src/d3/ray.rs | 6 +++--- examples/physics/raycast.rs | 2 ++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/crates/bevy_physics/src/d3/intersectors.rs b/crates/bevy_physics/src/d3/intersectors.rs index 40411aa099f0f..5a513af829839 100644 --- a/crates/bevy_physics/src/d3/intersectors.rs +++ b/crates/bevy_physics/src/d3/intersectors.rs @@ -53,15 +53,20 @@ impl RayIntersector for Sphere { if d < 0.0 { None } else { - let t = (-b - d.sqrt()) / (2.0 * a); + let distance = (-b - d.sqrt()) / (2.0 * a); - Some(RayHit::new(t, *ray.origin() + *ray.direction() * t)) + Some(RayHit::new( + distance, + *ray.origin() + *ray.direction() * distance, + )) } } } impl RayIntersector for Triangle { // using the Moeller-Trumbore intersection algorithm + // Can anyone think of sensible names for theese? + #[allow(clippy::many_single_char_names)] fn intersect_ray(&self, ray: &Ray) -> Option { let edges = (self.1 - self.0, self.2 - self.0); let h = ray.direction().cross(edges.1); @@ -86,10 +91,13 @@ impl RayIntersector for Triangle { return None; } - let t = f * edges.1.dot(q); + let distance = f * edges.1.dot(q); - if t > f32::EPSILON { - Some(RayHit::new(t, *ray.origin() + *ray.direction() * t)) + if distance > f32::EPSILON { + Some(RayHit::new( + distance, + *ray.origin() + *ray.direction() * distance, + )) } else { None } diff --git a/crates/bevy_physics/src/d3/ray.rs b/crates/bevy_physics/src/d3/ray.rs index 4aebe6dd290c9..cde45c70f0ad6 100644 --- a/crates/bevy_physics/src/d3/ray.rs +++ b/crates/bevy_physics/src/d3/ray.rs @@ -48,10 +48,10 @@ impl Ray { let near = near.truncate() / near.w; let far = far.truncate() / far.w; - let direction: Vec3 = (far - near).into(); - let origin: Vec3 = near.into(); + let direction: Vec3 = far - near; + let origin: Vec3 = near; - return Self { origin, direction }; + Self { origin, direction } } pub fn origin(&self) -> &Vec3 { diff --git a/examples/physics/raycast.rs b/examples/physics/raycast.rs index 33b50c3c3b55b..f77db4a501e2d 100644 --- a/examples/physics/raycast.rs +++ b/examples/physics/raycast.rs @@ -54,6 +54,8 @@ struct MouseState { cursor_position: Vec2, } +// Is there a way to reduce the arguments? +#[allow(clippy::too_many_arguments)] fn raycast( commands: &mut Commands, mut meshes: ResMut>, From 7bed2801058b9a53e5ce2088bafb83e432dec2d4 Mon Sep 17 00:00:00 2001 From: Marek Legris Date: Wed, 9 Dec 2020 11:48:53 +0100 Subject: [PATCH 12/12] changes for clippy --- crates/bevy_physics/src/d3/intersectors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_physics/src/d3/intersectors.rs b/crates/bevy_physics/src/d3/intersectors.rs index 5a513af829839..3ed874a53bb36 100644 --- a/crates/bevy_physics/src/d3/intersectors.rs +++ b/crates/bevy_physics/src/d3/intersectors.rs @@ -80,7 +80,7 @@ impl RayIntersector for Triangle { let s = *ray.origin() - self.0; let u = f * s.dot(h); - if u < 0.0 || u > 1.0 { + if !(0.0..=1.0).contains(&u) { return None; }