camera: break out projection components
This commit is contained in:
parent
db27d63b91
commit
fec9034644
@ -1,4 +1,4 @@
|
|||||||
use bevy_render::{Color, PerspectiveCamera};
|
use bevy_render::{Color, PerspectiveCamera, CameraProjection};
|
||||||
use bevy_transform::components::Translation;
|
use bevy_transform::components::Translation;
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use bevy_app::{Events, GetEventReader};
|
use bevy_app::{Events, GetEventReader};
|
||||||
use bevy_property::{Properties, Property};
|
use bevy_property::Properties;
|
||||||
use bevy_window::WindowResized;
|
use bevy_window::WindowResized;
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use legion::prelude::*;
|
use legion::{prelude::*, storage::Component};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Default, Properties)]
|
#[derive(Default, Properties)]
|
||||||
pub struct ActiveCamera;
|
pub struct ActiveCamera;
|
||||||
@ -11,7 +10,7 @@ pub struct ActiveCamera;
|
|||||||
#[derive(Default, Properties)]
|
#[derive(Default, Properties)]
|
||||||
pub struct ActiveCamera2d;
|
pub struct ActiveCamera2d;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Properties)]
|
||||||
pub struct OrthographicCamera {
|
pub struct OrthographicCamera {
|
||||||
pub left: f32,
|
pub left: f32,
|
||||||
pub right: f32,
|
pub right: f32,
|
||||||
@ -21,7 +20,7 @@ pub struct OrthographicCamera {
|
|||||||
pub far: f32,
|
pub far: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OrthographicCamera {
|
impl CameraProjection for OrthographicCamera {
|
||||||
fn get_view_matrix(&self) -> Mat4 {
|
fn get_view_matrix(&self) -> Mat4 {
|
||||||
let projection = Mat4::orthographic_rh_gl(
|
let projection = Mat4::orthographic_rh_gl(
|
||||||
self.left,
|
self.left,
|
||||||
@ -33,6 +32,10 @@ impl OrthographicCamera {
|
|||||||
);
|
);
|
||||||
projection
|
projection
|
||||||
}
|
}
|
||||||
|
fn update(&mut self, width: usize, height: usize) {
|
||||||
|
self.right = width as f32;
|
||||||
|
self.top = height as f32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for OrthographicCamera {
|
impl Default for OrthographicCamera {
|
||||||
@ -48,7 +51,12 @@ impl Default for OrthographicCamera {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
pub trait CameraProjection {
|
||||||
|
fn get_view_matrix(&self) -> Mat4;
|
||||||
|
fn update(&mut self, width: usize, height: usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Properties)]
|
||||||
pub struct PerspectiveCamera {
|
pub struct PerspectiveCamera {
|
||||||
pub fov: f32,
|
pub fov: f32,
|
||||||
pub aspect_ratio: f32,
|
pub aspect_ratio: f32,
|
||||||
@ -56,11 +64,14 @@ pub struct PerspectiveCamera {
|
|||||||
pub far: f32,
|
pub far: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PerspectiveCamera {
|
impl CameraProjection for PerspectiveCamera {
|
||||||
pub fn get_view_matrix(&self) -> Mat4 {
|
fn get_view_matrix(&self) -> Mat4 {
|
||||||
let projection = Mat4::perspective_rh_gl(self.fov, self.aspect_ratio, self.near, self.far);
|
let projection = Mat4::perspective_rh_gl(self.fov, self.aspect_ratio, self.near, self.far);
|
||||||
projection
|
projection
|
||||||
}
|
}
|
||||||
|
fn update(&mut self, width: usize, height: usize) {
|
||||||
|
self.aspect_ratio = width as f32 / height as f32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PerspectiveCamera {
|
impl Default for PerspectiveCamera {
|
||||||
@ -74,70 +85,22 @@ impl Default for PerspectiveCamera {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Property)]
|
|
||||||
pub enum CameraType {
|
|
||||||
Perspective(PerspectiveCamera),
|
|
||||||
Orthographic(OrthographicCamera),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CameraType {
|
|
||||||
pub fn default_perspective() -> CameraType {
|
|
||||||
CameraType::Perspective(PerspectiveCamera::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn default_orthographic() -> CameraType {
|
|
||||||
CameraType::Orthographic(OrthographicCamera::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CameraType {
|
|
||||||
fn default() -> Self {
|
|
||||||
CameraType::default_perspective()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Properties)]
|
#[derive(Default, Debug, Properties)]
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
pub view_matrix: Mat4,
|
pub view_matrix: Mat4,
|
||||||
pub camera_type: CameraType,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Camera {
|
pub fn camera_system<T: CameraProjection + Component>(resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||||
pub fn new(camera_type: CameraType) -> Self {
|
|
||||||
Camera {
|
|
||||||
view_matrix: Mat4::identity(),
|
|
||||||
camera_type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, width: u32, height: u32) {
|
|
||||||
self.view_matrix = match &mut self.camera_type {
|
|
||||||
CameraType::Perspective(projection) => {
|
|
||||||
projection.aspect_ratio = width as f32 / height as f32;
|
|
||||||
projection.get_view_matrix()
|
|
||||||
}
|
|
||||||
CameraType::Orthographic(orthographic) => {
|
|
||||||
orthographic.right = width as f32;
|
|
||||||
orthographic.top = height as f32;
|
|
||||||
orthographic.get_view_matrix()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn camera_update_system(resources: &mut Resources) -> Box<dyn Schedulable> {
|
|
||||||
let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>();
|
let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>();
|
||||||
(move |world: &mut SubWorld,
|
(move |world: &mut SubWorld,
|
||||||
window_resized_events: Res<Events<WindowResized>>,
|
window_resized_events: Res<Events<WindowResized>>,
|
||||||
query: &mut Query<Write<Camera>>| {
|
query: &mut Query<(Write<Camera>, Write<T>)>| {
|
||||||
let primary_window_resized_event = window_resized_event_reader
|
let primary_window_resized_event = window_resized_event_reader
|
||||||
.find_latest(&window_resized_events, |event| event.is_primary);
|
.find_latest(&window_resized_events, |event| event.is_primary);
|
||||||
if let Some(primary_window_resized_event) = primary_window_resized_event {
|
if let Some(primary_window_resized_event) = primary_window_resized_event {
|
||||||
for mut camera in query.iter_mut(world) {
|
for (mut camera, mut camera_projection) in query.iter_mut(world) {
|
||||||
camera.update(
|
camera_projection.update(primary_window_resized_event.width, primary_window_resized_event.height);
|
||||||
primary_window_resized_event.width,
|
camera.view_matrix = camera_projection.get_view_matrix();
|
||||||
primary_window_resized_event.height,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{mesh::Mesh, ActiveCamera, ActiveCamera2d, Camera, CameraType, Renderable};
|
use crate::{mesh::Mesh, ActiveCamera, ActiveCamera2d, Camera, Renderable, OrthographicCamera, PerspectiveCamera};
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_derive::EntityArchetype;
|
use bevy_derive::EntityArchetype;
|
||||||
use bevy_transform::components::{LocalToWorld, Rotation, Scale, Translation};
|
use bevy_transform::components::{LocalToWorld, Rotation, Scale, Translation};
|
||||||
@ -17,21 +17,14 @@ pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
|
|||||||
#[derive(EntityArchetype, Default)]
|
#[derive(EntityArchetype, Default)]
|
||||||
pub struct CameraEntity {
|
pub struct CameraEntity {
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
|
pub perspective_camera: PerspectiveCamera,
|
||||||
pub active_camera: ActiveCamera,
|
pub active_camera: ActiveCamera,
|
||||||
pub local_to_world: LocalToWorld,
|
pub local_to_world: LocalToWorld,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(EntityArchetype)]
|
#[derive(EntityArchetype, Default)]
|
||||||
pub struct Camera2dEntity {
|
pub struct OrthographicCameraEntity {
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
|
pub orthographic_camera: OrthographicCamera,
|
||||||
pub active_camera_2d: ActiveCamera2d,
|
pub active_camera_2d: ActiveCamera2d,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Camera2dEntity {
|
|
||||||
fn default() -> Self {
|
|
||||||
Camera2dEntity {
|
|
||||||
camera: Camera::new(CameraType::default_orthographic()),
|
|
||||||
active_camera_2d: ActiveCamera2d,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -76,11 +76,12 @@ impl AppPlugin for RenderPlugin {
|
|||||||
.add_asset::<PipelineDescriptor>()
|
.add_asset::<PipelineDescriptor>()
|
||||||
.add_asset_loader::<Texture, PngTextureLoader>()
|
.add_asset_loader::<Texture, PngTextureLoader>()
|
||||||
.register_component::<Camera>()
|
.register_component::<Camera>()
|
||||||
|
.register_component::<OrthographicCamera>()
|
||||||
|
.register_component::<PerspectiveCamera>()
|
||||||
.register_component::<Renderable>()
|
.register_component::<Renderable>()
|
||||||
.register_component::<ActiveCamera>()
|
.register_component::<ActiveCamera>()
|
||||||
.register_component::<ActiveCamera2d>()
|
.register_component::<ActiveCamera2d>()
|
||||||
.register_property_type::<Color>()
|
.register_property_type::<Color>()
|
||||||
.register_property_type::<CameraType>()
|
|
||||||
.register_property_type::<Range<f32>>()
|
.register_property_type::<Range<f32>>()
|
||||||
.init_resource::<RenderGraph>()
|
.init_resource::<RenderGraph>()
|
||||||
.init_resource::<PipelineAssignments>()
|
.init_resource::<PipelineAssignments>()
|
||||||
@ -91,7 +92,8 @@ impl AppPlugin for RenderPlugin {
|
|||||||
.init_resource::<EntitiesWaitingForAssets>()
|
.init_resource::<EntitiesWaitingForAssets>()
|
||||||
.init_resource::<TextureResourceSystemState>()
|
.init_resource::<TextureResourceSystemState>()
|
||||||
.add_system(entity_render_resource_assignments_system())
|
.add_system(entity_render_resource_assignments_system())
|
||||||
.init_system_to_stage(stage::POST_UPDATE, camera::camera_update_system)
|
.init_system_to_stage(stage::POST_UPDATE, camera::camera_system::<OrthographicCamera>)
|
||||||
|
.init_system_to_stage(stage::POST_UPDATE, camera::camera_system::<PerspectiveCamera>)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
stage::PRE_UPDATE,
|
stage::PRE_UPDATE,
|
||||||
EntitiesWaitingForAssets::clear_system.system(),
|
EntitiesWaitingForAssets::clear_system.system(),
|
||||||
|
@ -4,8 +4,8 @@ use super::{WindowDescriptor, WindowId};
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WindowResized {
|
pub struct WindowResized {
|
||||||
pub id: WindowId,
|
pub id: WindowId,
|
||||||
pub width: u32,
|
pub width: usize,
|
||||||
pub height: u32,
|
pub height: usize,
|
||||||
pub is_primary: bool,
|
pub is_primary: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +73,8 @@ pub fn winit_runner(mut app: App) {
|
|||||||
let mut resize_events = app.resources.get_mut::<Events<WindowResized>>().unwrap();
|
let mut resize_events = app.resources.get_mut::<Events<WindowResized>>().unwrap();
|
||||||
resize_events.send(WindowResized {
|
resize_events.send(WindowResized {
|
||||||
id: window_id,
|
id: window_id,
|
||||||
height: window.height,
|
height: window.height as usize,
|
||||||
width: window.width,
|
width: window.width as usize,
|
||||||
is_primary: windows.is_primary(window_id),
|
is_primary: windows.is_primary(window_id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ fn setup(
|
|||||||
let texture_handle = asset_server.load("assets/branding/icon.png").unwrap();
|
let texture_handle = asset_server.load("assets/branding/icon.png").unwrap();
|
||||||
command_buffer
|
command_buffer
|
||||||
.build()
|
.build()
|
||||||
.add_entity(Camera2dEntity::default())
|
.add_entity(OrthographicCameraEntity::default())
|
||||||
.add_entity(SpriteEntity {
|
.add_entity(SpriteEntity {
|
||||||
rect: Rect {
|
rect: Rect {
|
||||||
position: Vec2::new(300.0, 300.0),
|
position: Vec2::new(300.0, 300.0),
|
||||||
|
@ -25,7 +25,7 @@ fn setup(command_buffer: &mut CommandBuffer, asset_server: Res<AssetServer>) {
|
|||||||
command_buffer
|
command_buffer
|
||||||
.build()
|
.build()
|
||||||
// 2d camera
|
// 2d camera
|
||||||
.add_entity(Camera2dEntity::default())
|
.add_entity(OrthographicCameraEntity::default())
|
||||||
// texture
|
// texture
|
||||||
.add_entity(LabelEntity {
|
.add_entity(LabelEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
|
@ -58,7 +58,7 @@ fn setup(
|
|||||||
// ..Default::default()
|
// ..Default::default()
|
||||||
// })
|
// })
|
||||||
// 2d camera
|
// 2d camera
|
||||||
.add_entity(Camera2dEntity::default())
|
.add_entity(OrthographicCameraEntity::default())
|
||||||
// left vertical fill
|
// left vertical fill
|
||||||
.add_entity(UiEntity {
|
.add_entity(UiEntity {
|
||||||
node: Node::new(
|
node: Node::new(
|
||||||
|
@ -23,7 +23,7 @@ fn placement_system(
|
|||||||
|
|
||||||
fn setup(command_buffer: &mut CommandBuffer, mut materials: ResMut<Assets<ColorMaterial>>) {
|
fn setup(command_buffer: &mut CommandBuffer, mut materials: ResMut<Assets<ColorMaterial>>) {
|
||||||
let mut builder = command_buffer.build();
|
let mut builder = command_buffer.build();
|
||||||
builder.add_entity(Camera2dEntity::default());
|
builder.add_entity(OrthographicCameraEntity::default());
|
||||||
|
|
||||||
let mut prev = Vec2::default();
|
let mut prev = Vec2::default();
|
||||||
let count = 1000;
|
let count = 1000;
|
||||||
|
@ -30,7 +30,7 @@ pub use crate::render::{
|
|||||||
render_resource::resource_name,
|
render_resource::resource_name,
|
||||||
shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages},
|
shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages},
|
||||||
texture::{Texture, TextureType},
|
texture::{Texture, TextureType},
|
||||||
ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Renderable,
|
ActiveCamera, ActiveCamera2d, Camera, OrthographicCamera, PerspectiveCamera, Color, ColorSource, Renderable,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "scene")]
|
#[cfg(feature = "scene")]
|
||||||
pub use crate::scene::{Scene, SceneSpawner};
|
pub use crate::scene::{Scene, SceneSpawner};
|
||||||
|
Loading…
Reference in New Issue
Block a user