camera: make camera transform in world coordinates instead of the inverse
This commit is contained in:
		
							parent
							
								
									41dc8a5967
								
							
						
					
					
						commit
						3ee8aa8b0f
					
				
							
								
								
									
										19
									
								
								crates/bevy_core/src/transform/face_toward.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								crates/bevy_core/src/transform/face_toward.rs
									
									
									
									
									
										Normal file
									
								
							@ -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),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +1,7 @@
 | 
			
		||||
mod hierarchy;
 | 
			
		||||
mod world_builder;
 | 
			
		||||
mod face_toward;
 | 
			
		||||
 | 
			
		||||
pub use hierarchy::*;
 | 
			
		||||
pub use world_builder::*;
 | 
			
		||||
pub use face_toward::*;
 | 
			
		||||
 | 
			
		||||
@ -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(),
 | 
			
		||||
 | 
			
		||||
@ -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<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@ pub fn camera_system<T: CameraProjection + Component>() -> Box<dyn Schedulable>
 | 
			
		||||
            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<T: CameraProjection + Component>() -> Box<dyn Schedulable>
 | 
			
		||||
                    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();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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<VisibleEntity>,
 | 
			
		||||
}
 | 
			
		||||
@ -41,8 +42,8 @@ pub fn visible_entities_system(
 | 
			
		||||
 | 
			
		||||
            let order = if let Some(transform) = world.get_component::<Transform>(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
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -91,6 +91,10 @@ impl Node for MainPassNode {
 | 
			
		||||
                TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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::<VisibleEntities>(camera_entity).unwrap()
 | 
			
		||||
@ -98,10 +102,6 @@ impl Node for MainPassNode {
 | 
			
		||||
                        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::<Draw>(visible_entity.entity) {
 | 
			
		||||
@ -170,10 +170,10 @@ impl Node for MainPassNode {
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Tracks the current pipeline state to ensure draw calls are valid.
 | 
			
		||||
 | 
			
		||||
@ -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 }
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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::<Handle<StandardMaterial>>(visible_entity.entity) {
 | 
			
		||||
            if let Some(material_handle) =
 | 
			
		||||
                world.get_component::<Handle<StandardMaterial>>(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<Assets<StandardMaterial>>,
 | 
			
		||||
) {
 | 
			
		||||
    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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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),
 | 
			
		||||
 | 
			
		||||
@ -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},
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user