render: add more option for scaling modes of orthographic projection
This commit is contained in:
parent
c14c46f75d
commit
b2f0abf34d
|
@ -1,10 +1,40 @@
|
|||
use glam::{Mat4, Vec2};
|
||||
use lyra_ecs::{Bundle, Component};
|
||||
use lyra_math::Angle;
|
||||
use lyra_math::{Angle, Rect};
|
||||
use lyra_reflect::Reflect;
|
||||
|
||||
/// The method of scaling for an [`OrthographicProjection`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Reflect)]
|
||||
pub enum ScaleMode {
|
||||
/// No scaling, keep everything the same size as the viewport.
|
||||
Viewport,
|
||||
/// The width of the projection in world units.
|
||||
///
|
||||
/// Height will be set based off of the viewport's aspect ratio.
|
||||
Width(f32),
|
||||
/// The height of the projection in world units.
|
||||
///
|
||||
/// Width will be set based off of the viewport's aspect ratio.
|
||||
Height(f32),
|
||||
/// The exact size of the projection in world units.
|
||||
///
|
||||
/// Ignoring viewport size, likely causes stretching.
|
||||
Size(Vec2),
|
||||
/// Keep the projection size below a maximum value in world units, while keeping the aspect ratio.
|
||||
MaxSize(Vec2),
|
||||
/// Keep the projection size above a minimum value in world units, while keeping the aspect ratio.
|
||||
MinSize(Vec2),
|
||||
}
|
||||
|
||||
impl Default for ScaleMode {
|
||||
fn default() -> Self {
|
||||
ScaleMode::Viewport
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Reflect)]
|
||||
pub struct OrthographicProjection {
|
||||
pub scale_mode: ScaleMode,
|
||||
pub scale: f32,
|
||||
pub znear: f32,
|
||||
pub zfar: f32,
|
||||
|
@ -13,6 +43,7 @@ pub struct OrthographicProjection {
|
|||
impl Default for OrthographicProjection {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
scale_mode: Default::default(),
|
||||
scale: 1.0,
|
||||
znear: 0.0,
|
||||
zfar: 1000.0,
|
||||
|
@ -21,15 +52,63 @@ impl Default for OrthographicProjection {
|
|||
}
|
||||
|
||||
impl OrthographicProjection {
|
||||
fn get_rect(&self, viewport_size: Vec2) -> Rect {
|
||||
let origin;
|
||||
let size;
|
||||
|
||||
match self.scale_mode {
|
||||
ScaleMode::Viewport => {
|
||||
origin = viewport_size * 0.5;
|
||||
size = viewport_size;
|
||||
},
|
||||
ScaleMode::Width(width) => {
|
||||
let aspect = viewport_size.x / viewport_size.y;
|
||||
let origin_x = width * 0.5;
|
||||
let scaled_height = width / aspect;
|
||||
let origin_y = scaled_height * 0.5;
|
||||
|
||||
origin = Vec2::new(origin_x, origin_y);
|
||||
size = Vec2::new(width, scaled_height);
|
||||
},
|
||||
ScaleMode::Height(height) => {
|
||||
let aspect = viewport_size.x / viewport_size.y;
|
||||
let origin_y = height * 0.5;
|
||||
let scaled_width = height * aspect;
|
||||
let origin_x = scaled_width * 0.5;
|
||||
|
||||
origin = Vec2::new(origin_x, origin_y);
|
||||
size = Vec2::new(scaled_width, height);
|
||||
},
|
||||
ScaleMode::Size(s) => {
|
||||
origin = s * 0.5;
|
||||
size = s;
|
||||
},
|
||||
ScaleMode::MaxSize(s) => {
|
||||
let clamped = s.min(viewport_size);
|
||||
origin = clamped * 0.5;
|
||||
size = clamped;
|
||||
},
|
||||
ScaleMode::MinSize(s) => {
|
||||
let clamped = s.max(viewport_size);
|
||||
origin = clamped * 0.5;
|
||||
size = clamped;
|
||||
}
|
||||
}
|
||||
|
||||
Rect::new(self.scale * -origin.x,
|
||||
self.scale * -origin.y,
|
||||
self.scale * size.x - origin.x,
|
||||
self.scale * size.y - origin.y)
|
||||
}
|
||||
|
||||
pub fn to_mat(&self, viewport_size: Vec2) -> Mat4 {
|
||||
let origin_x = viewport_size.x as f32 * 0.5;
|
||||
let origin_y = viewport_size.y as f32 * 0.5;
|
||||
let rect = self.get_rect(viewport_size);
|
||||
|
||||
glam::Mat4::orthographic_rh(
|
||||
self.scale * -origin_x,
|
||||
self.scale * viewport_size.x as f32 - origin_x,
|
||||
self.scale * -origin_y,
|
||||
self.scale * viewport_size.y as f32 - origin_y,
|
||||
rect.min.x,
|
||||
rect.max.x,
|
||||
rect.min.y,
|
||||
rect.max.y,
|
||||
-1000.0,
|
||||
1000.0,
|
||||
)
|
||||
|
|
|
@ -7,6 +7,9 @@ pub use angle::*;
|
|||
mod area;
|
||||
pub use area::*;
|
||||
|
||||
mod rect;
|
||||
pub use rect::*;
|
||||
|
||||
pub mod transform;
|
||||
pub use transform::*;
|
||||
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
use glam::Vec2;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq)]
|
||||
pub struct Rect {
|
||||
pub min: Vec2,
|
||||
pub max: Vec2,
|
||||
}
|
||||
|
||||
impl Rect {
|
||||
pub fn new(x1: f32, y1: f32, x2: f32, y2: f32) -> Self {
|
||||
Self {
|
||||
min: Vec2::new(x1, y1),
|
||||
max: Vec2::new(x2, y2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_vec(min: Vec2, max: Vec2) -> Self {
|
||||
Self {
|
||||
min,
|
||||
max
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add for Rect {
|
||||
type Output = Rect;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Rect::from_vec(self.min + rhs.min, self.max + rhs.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::AddAssign for Rect {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.min += rhs.min;
|
||||
self.max += rhs.max;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub for Rect {
|
||||
type Output = Rect;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Rect::from_vec(self.min - rhs.min, self.max - rhs.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::SubAssign for Rect {
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
self.min -= rhs.min;
|
||||
self.max -= rhs.max;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul for Rect {
|
||||
type Output = Rect;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
Rect::from_vec(self.min * rhs.min, self.max * rhs.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::MulAssign for Rect {
|
||||
fn mul_assign(&mut self, rhs: Self) {
|
||||
self.min *= rhs.min;
|
||||
self.max *= rhs.max;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div for Rect {
|
||||
type Output = Rect;
|
||||
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
Rect::from_vec(self.min / rhs.min, self.max / rhs.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DivAssign for Rect {
|
||||
fn div_assign(&mut self, rhs: Self) {
|
||||
self.min /= rhs.min;
|
||||
self.max /= rhs.max;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ use lyra_engine::{
|
|||
math::{self, Transform, Vec3},
|
||||
render::light::directional::DirectionalLight,
|
||||
scene::{
|
||||
system_update_world_transforms, Camera2dBundle, CameraProjection, FreeFlyCamera, FreeFlyCameraPlugin, OrthographicProjection, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN
|
||||
system_update_world_transforms, Camera2dBundle, CameraProjection, FreeFlyCamera, FreeFlyCameraPlugin, OrthographicProjection, ScaleMode, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN
|
||||
},
|
||||
sprite::{self, Sprite},
|
||||
};
|
||||
|
@ -162,12 +162,16 @@ fn setup_scene_plugin(app: &mut App) {
|
|||
world.spawn((
|
||||
Camera2dBundle {
|
||||
projection: CameraProjection::Orthographic(OrthographicProjection {
|
||||
scale: 0.75,
|
||||
//scale_mode: ScaleMode::Width(960.0),
|
||||
scale_mode: ScaleMode::Height(180.0),
|
||||
//scale_mode: ScaleMode::Width(320.0),
|
||||
//scale_mode: ScaleMode::Size(lyra_engine::math::Vec2::new(320.0, 180.0)),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
Transform::from_xyz(200.0, 120.0, 0.0),
|
||||
//Transform::from_xyz(200.0, 120.0, 0.0),
|
||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||
FreeFlyCamera::default(),
|
||||
));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue