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 glam::{Mat4, Vec2};
|
||||||
use lyra_ecs::{Bundle, Component};
|
use lyra_ecs::{Bundle, Component};
|
||||||
use lyra_math::Angle;
|
use lyra_math::{Angle, Rect};
|
||||||
use lyra_reflect::Reflect;
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Reflect)]
|
||||||
pub struct OrthographicProjection {
|
pub struct OrthographicProjection {
|
||||||
|
pub scale_mode: ScaleMode,
|
||||||
pub scale: f32,
|
pub scale: f32,
|
||||||
pub znear: f32,
|
pub znear: f32,
|
||||||
pub zfar: f32,
|
pub zfar: f32,
|
||||||
|
@ -13,6 +43,7 @@ pub struct OrthographicProjection {
|
||||||
impl Default for OrthographicProjection {
|
impl Default for OrthographicProjection {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
scale_mode: Default::default(),
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
znear: 0.0,
|
znear: 0.0,
|
||||||
zfar: 1000.0,
|
zfar: 1000.0,
|
||||||
|
@ -21,15 +52,63 @@ impl Default for OrthographicProjection {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn to_mat(&self, viewport_size: Vec2) -> Mat4 {
|
||||||
let origin_x = viewport_size.x as f32 * 0.5;
|
let rect = self.get_rect(viewport_size);
|
||||||
let origin_y = viewport_size.y as f32 * 0.5;
|
|
||||||
|
|
||||||
glam::Mat4::orthographic_rh(
|
glam::Mat4::orthographic_rh(
|
||||||
self.scale * -origin_x,
|
rect.min.x,
|
||||||
self.scale * viewport_size.x as f32 - origin_x,
|
rect.max.x,
|
||||||
self.scale * -origin_y,
|
rect.min.y,
|
||||||
self.scale * viewport_size.y as f32 - origin_y,
|
rect.max.y,
|
||||||
-1000.0,
|
-1000.0,
|
||||||
1000.0,
|
1000.0,
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,6 +7,9 @@ pub use angle::*;
|
||||||
mod area;
|
mod area;
|
||||||
pub use area::*;
|
pub use area::*;
|
||||||
|
|
||||||
|
mod rect;
|
||||||
|
pub use rect::*;
|
||||||
|
|
||||||
pub mod transform;
|
pub mod transform;
|
||||||
pub use 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},
|
math::{self, Transform, Vec3},
|
||||||
render::light::directional::DirectionalLight,
|
render::light::directional::DirectionalLight,
|
||||||
scene::{
|
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},
|
sprite::{self, Sprite},
|
||||||
};
|
};
|
||||||
|
@ -162,12 +162,16 @@ fn setup_scene_plugin(app: &mut App) {
|
||||||
world.spawn((
|
world.spawn((
|
||||||
Camera2dBundle {
|
Camera2dBundle {
|
||||||
projection: CameraProjection::Orthographic(OrthographicProjection {
|
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()
|
||||||
}),
|
}),
|
||||||
..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(),
|
FreeFlyCamera::default(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue