From 3ee8aa8b0fcd87de885bbd483dde3e8203ba2f21 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Tue, 23 Jun 2020 19:15:05 -0700 Subject: [PATCH] camera: make camera transform in world coordinates instead of the inverse --- crates/bevy_core/src/transform/face_toward.rs | 19 ++++++++++++++ crates/bevy_core/src/transform/mod.rs | 2 ++ crates/bevy_pbr/src/light.rs | 2 +- crates/bevy_render/src/camera/camera.rs | 6 ++--- crates/bevy_render/src/camera/projection.rs | 6 ++--- .../src/camera/visible_entities.rs | 9 ++++--- .../src/render_graph/nodes/camera_node.rs | 2 +- .../src/render_graph/nodes/main_pass_node.rs | 26 +++++++++---------- .../src/components/transform.rs | 2 +- examples/3d/3d_scene.rs | 2 +- examples/3d/load_model.rs | 2 +- examples/3d/parenting.rs | 2 +- examples/3d/spawner.rs | 2 +- examples/3d/texture.rs | 2 +- examples/3d/z_sort_debug.rs | 9 ++++--- .../example_plugin/src/lib.rs | 2 +- examples/asset/asset_loading.rs | 2 +- examples/asset/hot_asset_reloading.rs | 2 +- examples/shader/shader_custom_material.rs | 2 +- examples/shader/shader_defs.rs | 2 +- examples/ui/ui.rs | 2 +- src/prelude.rs | 2 +- 22 files changed, 65 insertions(+), 42 deletions(-) create mode 100644 crates/bevy_core/src/transform/face_toward.rs diff --git a/crates/bevy_core/src/transform/face_toward.rs b/crates/bevy_core/src/transform/face_toward.rs new file mode 100644 index 0000000000..f743dd23d1 --- /dev/null +++ b/crates/bevy_core/src/transform/face_toward.rs @@ -0,0 +1,19 @@ +use glam::{Vec3, Mat4}; + +pub trait FaceToward { + fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self; +} + +impl FaceToward for Mat4 { + fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self { + let forward = (eye - center).normalize(); + let right = up.cross(forward).normalize(); + let up = forward.cross(right); + Mat4::from_cols( + right.extend(0.0), + up.extend(0.0), + forward.extend(0.0), + eye.extend(1.0), + ) + } +} diff --git a/crates/bevy_core/src/transform/mod.rs b/crates/bevy_core/src/transform/mod.rs index 6d749a0dfd..2f1723d0a4 100644 --- a/crates/bevy_core/src/transform/mod.rs +++ b/crates/bevy_core/src/transform/mod.rs @@ -1,5 +1,7 @@ mod hierarchy; mod world_builder; +mod face_toward; pub use hierarchy::*; pub use world_builder::*; +pub use face_toward::*; diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index ee224e7266..cfa6609d0d 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -41,7 +41,7 @@ impl LightRaw { far: light.depth.end, }; - let proj = perspective.get_view_matrix() * *transform; + let proj = perspective.get_projection_matrix() * *transform; let (x, y, z) = translation.0.into(); LightRaw { proj: proj.to_cols_array_2d(), diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index cb3375fd6f..a6ee21c565 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -7,7 +7,7 @@ use legion::{prelude::*, storage::Component}; #[derive(Default, Debug, Properties)] pub struct Camera { - pub view_matrix: Mat4, + pub projection_matrix: Mat4, pub name: Option, } @@ -29,7 +29,7 @@ pub fn camera_system() -> Box if let Some(window) = windows.get(event.id) { for (mut camera, mut camera_projection) in query.iter_mut(world) { camera_projection.update(window.width as usize, window.height as usize); - camera.view_matrix = camera_projection.get_view_matrix(); + camera.projection_matrix = camera_projection.get_projection_matrix(); } } } @@ -40,7 +40,7 @@ pub fn camera_system() -> Box primary_window_resized_event.width, primary_window_resized_event.height, ); - camera.view_matrix = camera_projection.get_view_matrix(); + camera.projection_matrix = camera_projection.get_projection_matrix(); } } }) diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 8cc17ff7f6..8324672e66 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -3,7 +3,7 @@ use glam::Mat4; use serde::{Deserialize, Serialize}; pub trait CameraProjection { - fn get_view_matrix(&self) -> Mat4; + fn get_projection_matrix(&self) -> Mat4; fn update(&mut self, width: usize, height: usize); } @@ -16,7 +16,7 @@ pub struct PerspectiveProjection { } impl CameraProjection for PerspectiveProjection { - fn get_view_matrix(&self) -> Mat4 { + fn get_projection_matrix(&self) -> Mat4 { let projection = Mat4::perspective_rh_gl(self.fov, self.aspect_ratio, self.near, self.far); projection } @@ -55,7 +55,7 @@ pub struct OrthographicProjection { } impl CameraProjection for OrthographicProjection { - fn get_view_matrix(&self) -> Mat4 { + fn get_projection_matrix(&self) -> Mat4 { let projection = Mat4::orthographic_rh( self.left, self.right, diff --git a/crates/bevy_render/src/camera/visible_entities.rs b/crates/bevy_render/src/camera/visible_entities.rs index 7f6fd56093..8da50ee2aa 100644 --- a/crates/bevy_render/src/camera/visible_entities.rs +++ b/crates/bevy_render/src/camera/visible_entities.rs @@ -7,12 +7,13 @@ use legion::{ systems::{Query, SubWorld}, }; +#[derive(Debug)] pub struct VisibleEntity { pub entity: Entity, pub order: FloatOrd, } -#[derive(Default)] +#[derive(Default, Debug)] pub struct VisibleEntities { pub value: Vec, } @@ -41,8 +42,8 @@ pub fn visible_entities_system( let order = if let Some(transform) = world.get_component::(entity) { let position = transform.value.w_axis().truncate(); - // smaller distances are sorted to lower indices by using the negative distance from the camera - FloatOrd(-(camera_position - position).length()) + // smaller distances are sorted to lower indices by using the distance from the camera + FloatOrd((camera_position - position).length()) } else { let order = FloatOrd(no_transform_order); no_transform_order += 0.1; @@ -54,7 +55,7 @@ pub fn visible_entities_system( }) } - visible_entities.value.sort_by_key(|e| e.order) + visible_entities.value.sort_by_key(|e| e.order); // TODO: check for big changes in visible entities len() vs capacity() (ex: 2x) and resize to prevent holding unneeded memory } diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index 08c859516c..49d90d1023 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -81,7 +81,7 @@ impl SystemNode for CameraNode { }; let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); - let camera_matrix: [f32; 16] = (camera.view_matrix * transform.value).to_cols_array(); + let camera_matrix: [f32; 16] = (camera.projection_matrix * transform.value.inverse()).to_cols_array(); let tmp_buffer = render_resource_context.create_buffer_mapped( BufferInfo { diff --git a/crates/bevy_render/src/render_graph/nodes/main_pass_node.rs b/crates/bevy_render/src/render_graph/nodes/main_pass_node.rs index e6fdb5d461..9e23d8f475 100644 --- a/crates/bevy_render/src/render_graph/nodes/main_pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/main_pass_node.rs @@ -91,17 +91,17 @@ impl Node for MainPassNode { TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap()); } - for camera_name in self.cameras.iter() { - let visible_entities = if let Some(camera_entity) = active_cameras.get(camera_name) { - world.get_component::(camera_entity).unwrap() - } else { - continue; - }; + render_context.begin_pass( + &self.descriptor, + &render_resource_bindings, + &mut |render_pass| { + for camera_name in self.cameras.iter() { + let visible_entities = if let Some(camera_entity) = active_cameras.get(camera_name) { + world.get_component::(camera_entity).unwrap() + } else { + continue; + }; - render_context.begin_pass( - &self.descriptor, - &render_resource_bindings, - &mut |render_pass| { let mut draw_state = DrawState::default(); for visible_entity in visible_entities.iter() { let draw = if let Some(draw) = world.get_component::(visible_entity.entity) { @@ -170,9 +170,9 @@ impl Node for MainPassNode { } } } - }, - ); - } + } + }, + ); } } diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index 53894161ba..aba1f7f80d 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -27,7 +27,7 @@ impl Transform { /// This creates a new `LocalToWorld` transform with the `sync` field set to `false`. /// While `sync` is false, position, rotation, and scale components will not be synced to the transform. - /// This is helpful if you want to manually set the transform to a value (ex: Mat4::look_at_rh) + /// This is helpful if you want to manually set the transform to a value (ex: Mat4::face_toward) #[inline(always)] pub fn new_sync_disabled(value: Mat4) -> Self { Transform { value, sync: false } diff --git a/examples/3d/3d_scene.rs b/examples/3d/3d_scene.rs index cf8faedc43..7637242f3e 100644 --- a/examples/3d/3d_scene.rs +++ b/examples/3d/3d_scene.rs @@ -50,7 +50,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(3.0, 8.0, 5.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/3d/load_model.rs b/examples/3d/load_model.rs index 887e9d068b..d2b7974108 100644 --- a/examples/3d/load_model.rs +++ b/examples/3d/load_model.rs @@ -39,7 +39,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(2.0, -6.0, 2.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/3d/parenting.rs b/examples/3d/parenting.rs index 28d8eff9e7..3f458e761b 100644 --- a/examples/3d/parenting.rs +++ b/examples/3d/parenting.rs @@ -53,7 +53,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(5.0, 10.0, 10.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/3d/spawner.rs b/examples/3d/spawner.rs index b06b4ce94e..c8f7ce3570 100644 --- a/examples/3d/spawner.rs +++ b/examples/3d/spawner.rs @@ -63,7 +63,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(3.0, 8.0, 5.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/3d/texture.rs b/examples/3d/texture.rs index 52db4a33ff..19434f1931 100644 --- a/examples/3d/texture.rs +++ b/examples/3d/texture.rs @@ -67,7 +67,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(3.0, -8.0, 5.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/3d/z_sort_debug.rs b/examples/3d/z_sort_debug.rs index 015991849e..c980b951b1 100644 --- a/examples/3d/z_sort_debug.rs +++ b/examples/3d/z_sort_debug.rs @@ -24,9 +24,11 @@ fn camera_order_color_system( ) { for (_camera, visible_entities) in camera_query.iter(world) { for visible_entity in visible_entities.iter() { - if let Some(material_handle) = world.get_component::>(visible_entity.entity) { + if let Some(material_handle) = + world.get_component::>(visible_entity.entity) + { let material = materials.get_mut(&material_handle).unwrap(); - let value = 1.0 - (20.0 + visible_entity.order.0) / 7.0; + let value = 1.0 - (visible_entity.order.0 - 10.0) / 7.0; material.albedo = Color::rgb(value, value, value); } } @@ -40,7 +42,6 @@ fn setup( mut materials: ResMut>, ) { let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 1.0 })); - command_buffer .build() // parent cube @@ -83,7 +84,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(5.0, 10.0, 10.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/app/dynamic_plugin_loading/example_plugin/src/lib.rs b/examples/app/dynamic_plugin_loading/example_plugin/src/lib.rs index 05012b5ebc..7c2a31553a 100644 --- a/examples/app/dynamic_plugin_loading/example_plugin/src/lib.rs +++ b/examples/app/dynamic_plugin_loading/example_plugin/src/lib.rs @@ -35,7 +35,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(3.0, 8.0, 5.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/asset/asset_loading.rs b/examples/asset/asset_loading.rs index b84a029abb..38d4cff54e 100644 --- a/examples/asset/asset_loading.rs +++ b/examples/asset/asset_loading.rs @@ -72,7 +72,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(0.0, -10.0, 3.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/asset/hot_asset_reloading.rs b/examples/asset/hot_asset_reloading.rs index fee91e155f..083837700b 100644 --- a/examples/asset/hot_asset_reloading.rs +++ b/examples/asset/hot_asset_reloading.rs @@ -47,7 +47,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(2.0, -6.0, 2.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/shader/shader_custom_material.rs b/examples/shader/shader_custom_material.rs index e2d4021ca4..4202680f99 100644 --- a/examples/shader/shader_custom_material.rs +++ b/examples/shader/shader_custom_material.rs @@ -103,7 +103,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(3.0, 8.0, 5.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index c5d0fc41db..4f022c0058 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -146,7 +146,7 @@ fn setup( }) // camera .add_entity(PerspectiveCameraEntity { - transform: Transform::new_sync_disabled(Mat4::look_at_rh( + transform: Transform::new_sync_disabled(Mat4::face_toward( Vec3::new(3.0, 8.0, 5.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 1.0), diff --git a/examples/ui/ui.rs b/examples/ui/ui.rs index d8d8ad58a9..8f4de48f38 100644 --- a/examples/ui/ui.rs +++ b/examples/ui/ui.rs @@ -48,7 +48,7 @@ fn setup( // }) // // 3d camera // .add_entity(CameraEntity { - // transform: Transform(Mat4::look_at_rh( + // transform: Transform(Mat4::face_toward( // Vec3::new(3.0, 8.0, 5.0), // Vec3::new(0.0, 0.0, 0.0), // Vec3::new(0.0, 0.0, 1.0), diff --git a/src/prelude.rs b/src/prelude.rs index c866e020e1..4ce8a7c7ae 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -6,7 +6,7 @@ pub use crate::{ asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle}, core::{ time::{Time, Timer}, - transform::{CommandBufferBuilderSource, WorldBuilder, WorldBuilderSource}, + transform::{CommandBufferBuilderSource, WorldBuilder, WorldBuilderSource, FaceToward}, }, diagnostic::DiagnosticsPlugin, input::{keyboard::KeyCode, mouse::MouseButton, Input},