Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Improve OrthographicCamera consistency and usability #6201

Closed
wants to merge 19 commits into from

Conversation

xgbwei
Copy link
Contributor

@xgbwei xgbwei commented Oct 8, 2022

Objective

  • Terminology used in field names and docs aren't accurate
  • window_origin doesn't have any effect when scaling_mode is ScalingMode::None
  • left, right, bottom, and top are set automatically unless scaling_mode is None. Fields that only sometimes give feedback are confusing.
  • ScalingMode::WindowSize has no arguments, which is inconsistent with other ScalingModes. 1 pixel = 1 world unit is also typically way too wide.
  • OrthographicProjection feels generally less streamlined than its PerspectiveProjection counterpart
  • Fixes Lack of documentation for OrthographicProjection #5818
  • Fixes OrthographicProjection's public fields are misleading #6190

Solution

  • Improve consistency in OrthographicProjection's public fields (they should either always give feedback or never give feedback).
  • Improve consistency in ScalingMode's arguments
  • General usability improvements
  • Improve accuracy of terminology:
    • "Window" should refer to the physical window on the desktop
    • "Viewport" should refer to the component in the window that images are drawn on (typically all of it)
    • "View frustum" should refer to the volume captured by the projection

Changelog

Added

  • Added argument to ScalingMode::WindowSize that specifies the number of pixels that equals one world unit.
  • Added documentation for fields and enums

Changed

  • Renamed window_origin to viewport_origin, which now:
    • Affects all ScalingModes
    • Takes a fraction of the viewport's width and height instead of an enum
      • Removed WindowOrigin enum as it's obsolete
  • Renamed ScalingMode::None to ScalingMode::Fixed, which now:
    • Takes arguments to specify the projection size
  • Replaced left, right, bottom, and top fields with a single area: Rect
  • scale is now applied before updating area. Reading from it will take scale into account.
  • Documentation changes to make terminology more accurate and consistent

Migration Guide

  • Change window_origin to viewport_origin; replace WindowOrigin::Center with Vec2::new(0.5, 0.5) and WindowOrigin::BottomLeft with Vec2::new(0.0, 0.0)
  • For shadow projections and such, replace left, right, bottom, and top with area: Rect::new(left, bottom, right, top)
  • For camera projections, remove l/r/b/t values from OrthographicProjection instantiations, as they no longer have any effect in any ScalingMode
  • Change ScalingMode::None to ScalingMode::Fixed
    • Replace manual changes of l/r/b/t with:
      • Arguments in ScalingMode::Fixed to specify size
      • viewport_origin to specify offset
  • Change ScalingMode::WindowSize to ScalingMode::WindowSize(1.0)

@alice-i-cecile alice-i-cecile added A-Rendering Drawing game state to the screen C-Usability A targeted quality-of-life change that makes Bevy easier to use labels Oct 8, 2022
@alice-i-cecile
Copy link
Member

Ping @bzm3r for review.

@xgbwei
Copy link
Contributor Author

xgbwei commented Oct 8, 2022

@alice-i-cecile shouldn't this be tagged with "breaking change"?

@alice-i-cecile alice-i-cecile added the M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide label Oct 8, 2022
@alice-i-cecile
Copy link
Member

Yep, thank you!

Copy link
Contributor

@bzm3r bzm3r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This looks good overall, and is much clearer to me than the old system.

I think the documentation still needs some clarification in some areas, but otherwise to my novice eyes, it looks okay.

/// Match the window size.
/// The argument is the number of pixels that equals one world unit.
WindowSize(f32),
/// Use the minimal possible projection size while keeping the aspect ratio.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain what is meant by "projection size"? Is this the same as the frustum's cross-section?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I think using "projection" as the plane that the frustum expands from makes it a bit simpler (rather than having to specify cross sectional area every time). I find it fairly intuitive but if you have any suggestions that's more than welcome.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xgbwei We can use projection, but then we should define it first. The issue is can mean multiple things in different contexts. (Also, what is intuitive to one reader might not be intuitive to another; that depends on the experiences the reader might have had.)

I think we should have a sentence that defines projection, and connects it to the idea of cross-sectional area, and then we can use projection. I will try and provide a suggestion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we need to take into account the near and far clipping planes as part of the "shape" of the projection. Clipping planes are mostly there for technical reasons, they aren't inherently part of orthographic projection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That being said, they should be taken into account when describing the view frustum, since frustum culling culls objects outside of the near and far clipping planes.

crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@sarkahn sarkahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few minor suggestions but I like the changes! Worth noting this breaks the current 2d examples as is - they all appear way more zoomed in than they should be. But that's just a matter of adjusting the defaults to be closer to how it was before.

crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
@xgbwei
Copy link
Contributor Author

xgbwei commented Oct 9, 2022

I have a few minor suggestions but I like the changes! Worth noting this breaks the current 2d examples as is - they all appear way more zoomed in than they should be. But that's just a matter of adjusting the defaults to be closer to how it was before.

Oh, I didn't notice that. That's probably because I made the default for WindowSize 10 since the camera is usually way too zoomed out by default, but I can change it back.

@superdump
Copy link
Contributor

I’d like to take a look at this if I get time.

@alice-i-cecile alice-i-cecile added the C-Docs An addition or correction to our documentation label Oct 9, 2022
Center,
BottomLeft,
}

#[derive(Debug, Clone, Reflect, FromReflect, Serialize, Deserialize)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[derive(Debug, Clone, Reflect, FromReflect, Serialize, Deserialize)]
/// Specifies how the size of a projection is calculated. The projection is the cross-sectional area
/// of the view frustum which intersects with the window.
#[derive(Debug, Clone, Reflect, FromReflect, Serialize, Deserialize)]

@xgbwei
Copy link
Contributor Author

xgbwei commented Oct 10, 2022

I'm trying to add a separate "config" struct for initializing, but it's a bit of a mess (and might be unnecessarily complicated). Maybe using a builder or just a simple constructor would work better?

I'm not sure if there's enough fields to warrant a builder, but there's too many fields to fit into constructor parameters comfortably. Are there any methods that would make configurating the fields ergonomic but also allow defaults?

@alice-i-cecile
Copy link
Member

Unfortunately no; you can't use struct update syntax unless the fields are pub. I think a builder pattern or an elaborate constructor is the way to go.

/// projection. When the projection scales, the position of the camera doesn't change, and since `viewport_origin`
/// specifies the point on the viewport where the camera sits, this point will always remain at the same position
/// (relative to the viewport size; if `viewport_origin` is (0.3, 0.6), objects at (0.3, 0.6) (normalized) on the
/// viewport will always remain at (0.3, 0.6) (normalized).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to make this as specific as possible. Looking for ways to make it simpler.

crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@djeedai djeedai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the change! I salute the documenting part which is much welcome ♥️ But I'm more skeptical about the builder pattern refactoring. For one, it feels those two changes are unrelated and should maybe be done in separate PRs. I also personally don't like the pattern so much, mostly as it increases inconsistency with the rest of the Bevy codebase.

crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
crates/bevy_render/src/camera/projection.rs Outdated Show resolved Hide resolved
examples/3d/lighting.rs Outdated Show resolved Hide resolved
examples/3d/orthographic.rs Outdated Show resolved Hide resolved
examples/3d/shadow_biases.rs Outdated Show resolved Hide resolved
@xgbwei
Copy link
Contributor Author

xgbwei commented Nov 8, 2022

Thanks for the change! I salute the documenting part which is much welcome ♥️ But I'm more skeptical about the builder pattern refactoring. For one, it feels those two changes are unrelated and should maybe be done in separate PRs. I also personally don't like the pattern so much, mostly as it increases inconsistency with the rest of the Bevy codebase.

I sort of agree with this. Do you have any suggestions for alternatives? Every other method I've looked at has had some other downside. I could also just leave the fields public.

@djeedai
Copy link
Contributor

djeedai commented Nov 8, 2022

I sort of agree with this. Do you have any suggestions for alternatives? Every other method I've looked at has had some other downside. I could also just leave the fields public.

Because this is the recommended and promoted pattern in the rest of the codebase, yes I would just leave those as public fields for now. We can discuss whether this is the right pattern or not (I doubt we can convince anyone of a change at this point though), but I wouldn't make this object inconsistent unless there's an overwhelming benefit to the builder pattern, which I don't think we showed here.

@xgbwei
Copy link
Contributor Author

xgbwei commented Nov 8, 2022

Because this is the recommended and promoted pattern in the rest of the codebase, yes I would just leave those as public fields for now. We can discuss whether this is the right pattern or not (I doubt we can convince anyone of a change at this point though), but I wouldn't make this object inconsistent unless there's an overwhelming benefit to the builder pattern, which I don't think we showed here.

That's fair. Clearly documenting that l/r/b/t should be for reading only should be fine for now.

examples/3d/load_gltf.rs Outdated Show resolved Hide resolved
@xgbwei
Copy link
Contributor Author

xgbwei commented Feb 8, 2023

Did I do that right?

@alice-i-cecile
Copy link
Member

Rebase looks almost correct: you have an empty scene_viewer file :)

@alice-i-cecile
Copy link
Member

bors r+

bors bot pushed a commit that referenced this pull request Feb 8, 2023
# Objective

- Terminology used in field names and docs aren't accurate
- `window_origin` doesn't have any effect when `scaling_mode` is `ScalingMode::None`
- `left`, `right`, `bottom`, and `top` are set automatically unless `scaling_mode` is `None`. Fields that only sometimes give feedback are confusing.
- `ScalingMode::WindowSize` has no arguments, which is inconsistent with other `ScalingMode`s. 1 pixel = 1 world unit is also typically way too wide.
- `OrthographicProjection` feels generally less streamlined than its `PerspectiveProjection` counterpart
- Fixes #5818 
- Fixes #6190 

## Solution

- Improve consistency in `OrthographicProjection`'s public fields (they should either always give feedback or never give feedback).
- Improve consistency in `ScalingMode`'s arguments
- General usability improvements
- Improve accuracy of terminology:
  - "Window" should refer to the physical window on the desktop
  - "Viewport" should refer to the component in the window that images are drawn on (typically all of it)
  - "View frustum" should refer to the volume captured by the projection

---

## Changelog

### Added
- Added argument to `ScalingMode::WindowSize` that specifies the number of pixels that equals one world unit.
- Added documentation for fields and enums

### Changed
- Renamed `window_origin` to `viewport_origin`, which now:
  - Affects all `ScalingMode`s
  - Takes a fraction of the viewport's width and height instead of an enum
    - Removed `WindowOrigin` enum as it's obsolete
- Renamed `ScalingMode::None` to `ScalingMode::Fixed`, which now:
  - Takes arguments to specify the projection size
- Replaced `left`, `right`, `bottom`, and `top` fields with a single `area: Rect`
- `scale` is now applied before updating `area`. Reading from it will take `scale` into account.
- Documentation changes to make terminology more accurate and consistent

## Migration Guide
- Change `window_origin` to `viewport_origin`; replace `WindowOrigin::Center` with `Vec2::new(0.5, 0.5)` and `WindowOrigin::BottomLeft` with `Vec2::new(0.0, 0.0)`
- For shadow projections and such, replace `left`, `right`, `bottom`, and `top` with `area: Rect::new(left, bottom, right, top)`
- For camera projections, remove l/r/b/t values from `OrthographicProjection` instantiations, as they no longer have any effect in any `ScalingMode`
- Change `ScalingMode::None` to `ScalingMode::Fixed`
  - Replace manual changes of l/r/b/t with:
    - Arguments in `ScalingMode::Fixed` to specify size
    - `viewport_origin` to specify offset
- Change `ScalingMode::WindowSize` to `ScalingMode::WindowSize(1.0)`
@bors bors bot changed the title Improve OrthographicCamera consistency and usability [Merged by Bors] - Improve OrthographicCamera consistency and usability Feb 8, 2023
@bors bors bot closed this Feb 8, 2023
myreprise1 pushed a commit to myreprise1/bevy that referenced this pull request Feb 11, 2023
# Objective

- Terminology used in field names and docs aren't accurate
- `window_origin` doesn't have any effect when `scaling_mode` is `ScalingMode::None`
- `left`, `right`, `bottom`, and `top` are set automatically unless `scaling_mode` is `None`. Fields that only sometimes give feedback are confusing.
- `ScalingMode::WindowSize` has no arguments, which is inconsistent with other `ScalingMode`s. 1 pixel = 1 world unit is also typically way too wide.
- `OrthographicProjection` feels generally less streamlined than its `PerspectiveProjection` counterpart
- Fixes bevyengine#5818 
- Fixes bevyengine#6190 

## Solution

- Improve consistency in `OrthographicProjection`'s public fields (they should either always give feedback or never give feedback).
- Improve consistency in `ScalingMode`'s arguments
- General usability improvements
- Improve accuracy of terminology:
  - "Window" should refer to the physical window on the desktop
  - "Viewport" should refer to the component in the window that images are drawn on (typically all of it)
  - "View frustum" should refer to the volume captured by the projection

---

## Changelog

### Added
- Added argument to `ScalingMode::WindowSize` that specifies the number of pixels that equals one world unit.
- Added documentation for fields and enums

### Changed
- Renamed `window_origin` to `viewport_origin`, which now:
  - Affects all `ScalingMode`s
  - Takes a fraction of the viewport's width and height instead of an enum
    - Removed `WindowOrigin` enum as it's obsolete
- Renamed `ScalingMode::None` to `ScalingMode::Fixed`, which now:
  - Takes arguments to specify the projection size
- Replaced `left`, `right`, `bottom`, and `top` fields with a single `area: Rect`
- `scale` is now applied before updating `area`. Reading from it will take `scale` into account.
- Documentation changes to make terminology more accurate and consistent

## Migration Guide
- Change `window_origin` to `viewport_origin`; replace `WindowOrigin::Center` with `Vec2::new(0.5, 0.5)` and `WindowOrigin::BottomLeft` with `Vec2::new(0.0, 0.0)`
- For shadow projections and such, replace `left`, `right`, `bottom`, and `top` with `area: Rect::new(left, bottom, right, top)`
- For camera projections, remove l/r/b/t values from `OrthographicProjection` instantiations, as they no longer have any effect in any `ScalingMode`
- Change `ScalingMode::None` to `ScalingMode::Fixed`
  - Replace manual changes of l/r/b/t with:
    - Arguments in `ScalingMode::Fixed` to specify size
    - `viewport_origin` to specify offset
- Change `ScalingMode::WindowSize` to `ScalingMode::WindowSize(1.0)`
myreprise1 pushed a commit to myreprise1/bevy that referenced this pull request Feb 11, 2023
# Objective

- Terminology used in field names and docs aren't accurate
- `window_origin` doesn't have any effect when `scaling_mode` is `ScalingMode::None`
- `left`, `right`, `bottom`, and `top` are set automatically unless `scaling_mode` is `None`. Fields that only sometimes give feedback are confusing.
- `ScalingMode::WindowSize` has no arguments, which is inconsistent with other `ScalingMode`s. 1 pixel = 1 world unit is also typically way too wide.
- `OrthographicProjection` feels generally less streamlined than its `PerspectiveProjection` counterpart
- Fixes bevyengine#5818 
- Fixes bevyengine#6190 

## Solution

- Improve consistency in `OrthographicProjection`'s public fields (they should either always give feedback or never give feedback).
- Improve consistency in `ScalingMode`'s arguments
- General usability improvements
- Improve accuracy of terminology:
  - "Window" should refer to the physical window on the desktop
  - "Viewport" should refer to the component in the window that images are drawn on (typically all of it)
  - "View frustum" should refer to the volume captured by the projection

---

## Changelog

### Added
- Added argument to `ScalingMode::WindowSize` that specifies the number of pixels that equals one world unit.
- Added documentation for fields and enums

### Changed
- Renamed `window_origin` to `viewport_origin`, which now:
  - Affects all `ScalingMode`s
  - Takes a fraction of the viewport's width and height instead of an enum
    - Removed `WindowOrigin` enum as it's obsolete
- Renamed `ScalingMode::None` to `ScalingMode::Fixed`, which now:
  - Takes arguments to specify the projection size
- Replaced `left`, `right`, `bottom`, and `top` fields with a single `area: Rect`
- `scale` is now applied before updating `area`. Reading from it will take `scale` into account.
- Documentation changes to make terminology more accurate and consistent

## Migration Guide
- Change `window_origin` to `viewport_origin`; replace `WindowOrigin::Center` with `Vec2::new(0.5, 0.5)` and `WindowOrigin::BottomLeft` with `Vec2::new(0.0, 0.0)`
- For shadow projections and such, replace `left`, `right`, `bottom`, and `top` with `area: Rect::new(left, bottom, right, top)`
- For camera projections, remove l/r/b/t values from `OrthographicProjection` instantiations, as they no longer have any effect in any `ScalingMode`
- Change `ScalingMode::None` to `ScalingMode::Fixed`
  - Replace manual changes of l/r/b/t with:
    - Arguments in `ScalingMode::Fixed` to specify size
    - `viewport_origin` to specify offset
- Change `ScalingMode::WindowSize` to `ScalingMode::WindowSize(1.0)`
myreprise1 pushed a commit to myreprise1/bevy that referenced this pull request Feb 15, 2023
# Objective

- Terminology used in field names and docs aren't accurate
- `window_origin` doesn't have any effect when `scaling_mode` is `ScalingMode::None`
- `left`, `right`, `bottom`, and `top` are set automatically unless `scaling_mode` is `None`. Fields that only sometimes give feedback are confusing.
- `ScalingMode::WindowSize` has no arguments, which is inconsistent with other `ScalingMode`s. 1 pixel = 1 world unit is also typically way too wide.
- `OrthographicProjection` feels generally less streamlined than its `PerspectiveProjection` counterpart
- Fixes bevyengine#5818 
- Fixes bevyengine#6190 

## Solution

- Improve consistency in `OrthographicProjection`'s public fields (they should either always give feedback or never give feedback).
- Improve consistency in `ScalingMode`'s arguments
- General usability improvements
- Improve accuracy of terminology:
  - "Window" should refer to the physical window on the desktop
  - "Viewport" should refer to the component in the window that images are drawn on (typically all of it)
  - "View frustum" should refer to the volume captured by the projection

---

## Changelog

### Added
- Added argument to `ScalingMode::WindowSize` that specifies the number of pixels that equals one world unit.
- Added documentation for fields and enums

### Changed
- Renamed `window_origin` to `viewport_origin`, which now:
  - Affects all `ScalingMode`s
  - Takes a fraction of the viewport's width and height instead of an enum
    - Removed `WindowOrigin` enum as it's obsolete
- Renamed `ScalingMode::None` to `ScalingMode::Fixed`, which now:
  - Takes arguments to specify the projection size
- Replaced `left`, `right`, `bottom`, and `top` fields with a single `area: Rect`
- `scale` is now applied before updating `area`. Reading from it will take `scale` into account.
- Documentation changes to make terminology more accurate and consistent

## Migration Guide
- Change `window_origin` to `viewport_origin`; replace `WindowOrigin::Center` with `Vec2::new(0.5, 0.5)` and `WindowOrigin::BottomLeft` with `Vec2::new(0.0, 0.0)`
- For shadow projections and such, replace `left`, `right`, `bottom`, and `top` with `area: Rect::new(left, bottom, right, top)`
- For camera projections, remove l/r/b/t values from `OrthographicProjection` instantiations, as they no longer have any effect in any `ScalingMode`
- Change `ScalingMode::None` to `ScalingMode::Fixed`
  - Replace manual changes of l/r/b/t with:
    - Arguments in `ScalingMode::Fixed` to specify size
    - `viewport_origin` to specify offset
- Change `ScalingMode::WindowSize` to `ScalingMode::WindowSize(1.0)`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Docs An addition or correction to our documentation C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

OrthographicProjection's public fields are misleading Lack of documentation for OrthographicProjection
7 participants