mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
camera: make camera transform in world coordinates instead of the inverse
This commit is contained in:
parent
41dc8a5967
commit
3ee8aa8b0f
22 changed files with 65 additions and 42 deletions
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,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::<VisibleEntities>(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::<VisibleEntities>(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::<Draw>(visible_entity.entity) {
|
||||
|
@ -170,9 +170,9 @@ impl Node for MainPassNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 a new issue