Projection
Improvements (#18458)
# Objective - Remove a component impl footgun - Make projection code slightly nicer, and remove the need to import the projection trait when using the methods on `Projection`. ## Solution - Do the things.
This commit is contained in:
parent
82d62e606c
commit
3cefe82aff
@ -7,7 +7,7 @@ use bevy_ecs::{
|
|||||||
use bevy_math::{ops, Mat4, Vec3A, Vec4};
|
use bevy_math::{ops, Mat4, Vec3A, Vec4};
|
||||||
use bevy_reflect::prelude::*;
|
use bevy_reflect::prelude::*;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::{Camera, CameraProjection, Projection},
|
camera::{Camera, Projection},
|
||||||
extract_component::ExtractComponent,
|
extract_component::ExtractComponent,
|
||||||
extract_resource::ExtractResource,
|
extract_resource::ExtractResource,
|
||||||
mesh::Mesh3d,
|
mesh::Mesh3d,
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
use super::{ClearColorConfig, Projection};
|
use super::{ClearColorConfig, Projection};
|
||||||
use crate::{
|
use crate::{
|
||||||
batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport},
|
batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport},
|
||||||
camera::{CameraProjection, ManualTextureViewHandle, ManualTextureViews},
|
camera::{ManualTextureViewHandle, ManualTextureViews},
|
||||||
primitives::Frustum,
|
primitives::Frustum,
|
||||||
render_asset::RenderAssets,
|
render_asset::RenderAssets,
|
||||||
render_graph::{InternedRenderSubGraph, RenderSubGraph},
|
render_graph::{InternedRenderSubGraph, RenderSubGraph},
|
||||||
@ -311,8 +311,8 @@ pub enum ViewportConversionError {
|
|||||||
#[error("computed coordinate beyond `Camera`'s far plane")]
|
#[error("computed coordinate beyond `Camera`'s far plane")]
|
||||||
PastFarPlane,
|
PastFarPlane,
|
||||||
/// The Normalized Device Coordinates could not be computed because the `camera_transform`, the
|
/// The Normalized Device Coordinates could not be computed because the `camera_transform`, the
|
||||||
/// `world_position`, or the projection matrix defined by [`CameraProjection`] contained `NAN`
|
/// `world_position`, or the projection matrix defined by [`Projection`] contained `NAN` (see
|
||||||
/// (see [`world_to_ndc`][Camera::world_to_ndc] and [`ndc_to_world`][Camera::ndc_to_world]).
|
/// [`world_to_ndc`][Camera::world_to_ndc] and [`ndc_to_world`][Camera::ndc_to_world]).
|
||||||
#[error("found NaN while computing NDC")]
|
#[error("found NaN while computing NDC")]
|
||||||
InvalidData,
|
InvalidData,
|
||||||
}
|
}
|
||||||
@ -490,7 +490,7 @@ impl Camera {
|
|||||||
.map(|t: &RenderTargetInfo| t.scale_factor)
|
.map(|t: &RenderTargetInfo| t.scale_factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The projection matrix computed using this camera's [`CameraProjection`].
|
/// The projection matrix computed using this camera's [`Projection`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clip_from_view(&self) -> Mat4 {
|
pub fn clip_from_view(&self) -> Mat4 {
|
||||||
self.computed.clip_from_view
|
self.computed.clip_from_view
|
||||||
@ -655,7 +655,7 @@ impl Camera {
|
|||||||
/// To get the coordinates in the render target's viewport dimensions, you should use
|
/// To get the coordinates in the render target's viewport dimensions, you should use
|
||||||
/// [`world_to_viewport`](Self::world_to_viewport).
|
/// [`world_to_viewport`](Self::world_to_viewport).
|
||||||
///
|
///
|
||||||
/// Returns `None` if the `camera_transform`, the `world_position`, or the projection matrix defined by [`CameraProjection`] contain `NAN`.
|
/// Returns `None` if the `camera_transform`, the `world_position`, or the projection matrix defined by [`Projection`] contain `NAN`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
@ -681,7 +681,7 @@ impl Camera {
|
|||||||
/// To get the world space coordinates with the viewport position, you should use
|
/// To get the world space coordinates with the viewport position, you should use
|
||||||
/// [`world_to_viewport`](Self::world_to_viewport).
|
/// [`world_to_viewport`](Self::world_to_viewport).
|
||||||
///
|
///
|
||||||
/// Returns `None` if the `camera_transform`, the `world_position`, or the projection matrix defined by [`CameraProjection`] contain `NAN`.
|
/// Returns `None` if the `camera_transform`, the `world_position`, or the projection matrix defined by [`Projection`] contain `NAN`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
use core::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use crate::{primitives::Frustum, view::VisibilitySystems};
|
use crate::{primitives::Frustum, view::VisibilitySystems};
|
||||||
use bevy_app::{App, Plugin, PostStartup, PostUpdate};
|
use bevy_app::{App, Plugin, PostStartup, PostUpdate};
|
||||||
use bevy_asset::AssetEventSystems;
|
use bevy_asset::AssetEventSystems;
|
||||||
use bevy_derive::{Deref, DerefMut};
|
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_math::{ops, AspectRatio, Mat4, Rect, Vec2, Vec3A, Vec4};
|
use bevy_math::{ops, AspectRatio, Mat4, Rect, Vec2, Vec3A, Vec4};
|
||||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect, ReflectDeserialize, ReflectSerialize};
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect, ReflectDeserialize, ReflectSerialize};
|
||||||
@ -131,11 +131,10 @@ mod sealed {
|
|||||||
/// custom projection.
|
/// custom projection.
|
||||||
///
|
///
|
||||||
/// The contained dynamic object can be downcast into a static type using [`CustomProjection::get`].
|
/// The contained dynamic object can be downcast into a static type using [`CustomProjection::get`].
|
||||||
#[derive(Component, Debug, Reflect, Deref, DerefMut)]
|
#[derive(Debug, Reflect)]
|
||||||
#[reflect(Default, Clone)]
|
#[reflect(Default, Clone)]
|
||||||
pub struct CustomProjection {
|
pub struct CustomProjection {
|
||||||
#[reflect(ignore)]
|
#[reflect(ignore)]
|
||||||
#[deref]
|
|
||||||
dyn_projection: Box<dyn sealed::DynCameraProjection>,
|
dyn_projection: Box<dyn sealed::DynCameraProjection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,6 +203,20 @@ impl CustomProjection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for CustomProjection {
|
||||||
|
type Target = dyn CameraProjection;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.dyn_projection.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for CustomProjection {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
self.dyn_projection.as_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Component that defines how to compute a [`Camera`]'s projection matrix.
|
/// Component that defines how to compute a [`Camera`]'s projection matrix.
|
||||||
///
|
///
|
||||||
/// Common projections, like perspective and orthographic, are provided out of the box to handle the
|
/// Common projections, like perspective and orthographic, are provided out of the box to handle the
|
||||||
@ -240,7 +253,7 @@ impl Projection {
|
|||||||
// that, say, the `Debug` implementation is missing. Wrapping these traits behind a super
|
// that, say, the `Debug` implementation is missing. Wrapping these traits behind a super
|
||||||
// trait or some other indirection will make the errors harder to understand.
|
// trait or some other indirection will make the errors harder to understand.
|
||||||
//
|
//
|
||||||
// For example, we don't use the `DynCameraProjection`` trait bound, because it is not the
|
// For example, we don't use the `DynCameraProjection` trait bound, because it is not the
|
||||||
// trait the user should be implementing - they only need to worry about implementing
|
// trait the user should be implementing - they only need to worry about implementing
|
||||||
// `CameraProjection`.
|
// `CameraProjection`.
|
||||||
P: CameraProjection + Debug + Send + Sync + Clone + 'static,
|
P: CameraProjection + Debug + Send + Sync + Clone + 'static,
|
||||||
@ -251,44 +264,24 @@ impl Projection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CameraProjection for Projection {
|
impl Deref for Projection {
|
||||||
fn get_clip_from_view(&self) -> Mat4 {
|
type Target = dyn CameraProjection;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
match self {
|
match self {
|
||||||
Projection::Perspective(projection) => projection.get_clip_from_view(),
|
Projection::Perspective(projection) => projection,
|
||||||
Projection::Orthographic(projection) => projection.get_clip_from_view(),
|
Projection::Orthographic(projection) => projection,
|
||||||
Projection::Custom(projection) => projection.get_clip_from_view(),
|
Projection::Custom(projection) => projection.deref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_clip_from_view_for_sub(&self, sub_view: &super::SubCameraView) -> Mat4 {
|
impl DerefMut for Projection {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
match self {
|
match self {
|
||||||
Projection::Perspective(projection) => projection.get_clip_from_view_for_sub(sub_view),
|
Projection::Perspective(projection) => projection,
|
||||||
Projection::Orthographic(projection) => projection.get_clip_from_view_for_sub(sub_view),
|
Projection::Orthographic(projection) => projection,
|
||||||
Projection::Custom(projection) => projection.get_clip_from_view_for_sub(sub_view),
|
Projection::Custom(projection) => projection.deref_mut(),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, width: f32, height: f32) {
|
|
||||||
match self {
|
|
||||||
Projection::Perspective(projection) => projection.update(width, height),
|
|
||||||
Projection::Orthographic(projection) => projection.update(width, height),
|
|
||||||
Projection::Custom(projection) => projection.update(width, height),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn far(&self) -> f32 {
|
|
||||||
match self {
|
|
||||||
Projection::Perspective(projection) => projection.far(),
|
|
||||||
Projection::Orthographic(projection) => projection.far(),
|
|
||||||
Projection::Custom(projection) => projection.far(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8] {
|
|
||||||
match self {
|
|
||||||
Projection::Perspective(projection) => projection.get_frustum_corners(z_near, z_far),
|
|
||||||
Projection::Orthographic(projection) => projection.get_frustum_corners(z_near, z_far),
|
|
||||||
Projection::Custom(projection) => projection.get_frustum_corners(z_near, z_far),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ use smallvec::SmallVec;
|
|||||||
|
|
||||||
use super::NoCpuCulling;
|
use super::NoCpuCulling;
|
||||||
use crate::{
|
use crate::{
|
||||||
camera::{Camera, CameraProjection, Projection},
|
camera::{Camera, Projection},
|
||||||
mesh::{Mesh, Mesh3d, MeshAabb},
|
mesh::{Mesh, Mesh3d, MeshAabb},
|
||||||
primitives::{Aabb, Frustum, Sphere},
|
primitives::{Aabb, Frustum, Sphere},
|
||||||
sync_world::MainEntity,
|
sync_world::MainEntity,
|
||||||
|
Loading…
Reference in New Issue
Block a user