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

PerspectiveCamera: New helper methods getFrustumBounds(), getFrustumSize(). #27574

Merged
merged 27 commits into from
Jan 19, 2024

Conversation

Bug-Reaper
Copy link
Contributor

@Bug-Reaper Bug-Reaper commented Jan 17, 2024

Related #27556

Description

A PerspectiveCamera's viewable margins at an arbitrary distance is a foundational piece of info you can build a lot of clean experiences from. This PR adds 2 new helper methods to PerspectiveCamera intended to make it easy for developers to create cool experiences where viewable area is a consideration.

Some common use-cases include:
  • Guarantee your rendered content fits on the screen.
  • Scale 3D content to take up an exact percentage of available screen height/width.
  • Situations where you want to have objects cleanly enter and exit the visible area.
  • Reset a user controlled camera to an ideal-default.
  • Place a backdrop plane that exactly covers the visible area.

Methods added to PerspectiveCamera:

1️⃣ getFrustumBounds()

 getBounds( distance : Float, minTarget : Vector2, maxTarget : Vector2 ) : undefined

Calculates the XY of the min/max bounds for the camera's viewable rectangle at a given distance. Results are copied into minTarget and maxTarget input vars.

2️⃣ getFrustumSize()

 frustumDimensions( distance : Float, target : Vector2 ) : Vector2

Calculates the height and width of the camera's frustum at a given distance from the camera. Copies results into the target Vector2 where x is width and y is height.

Method added to CameraUtils To be addressed in separate PR:

getFrustumCorners()

 frustumCorners( camera : PerspectiveCamera , distance : Float ) : Object

Provides positions of the camera's frustum corners at a given distance from the camera. Returns an object with topLeft, topRight, bottomRight, and bottomLeft properties where each property is a Vector3.


*This contribution is supported by SoundSafari (shameless plug for my solo art project) drawing

Copy link

github-actions bot commented Jan 17, 2024

📦 Bundle size

Full ESM build, minified and gzipped.

Filesize dev Filesize PR Diff
673.1 kB (167.1 kB) 673.5 kB (167.2 kB) +326 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Filesize dev Filesize PR Diff
453.9 kB (110.1 kB) 454.2 kB (110.1 kB) +326 B

@Mugen87 Mugen87 added this to the r161 milestone Jan 17, 2024
@Bug-Reaper
Copy link
Contributor Author

Made these review upgrades 🦾 plan to commit doc updates to match with the changes shortly

// .applyMatrix4() -> Accounts for camera position/rotation/scale
return {
topLeft: _vec.set( _minTarget.x, _maxTarget.y, - distance ).applyMatrix4( camera.matrixWorld ).clone(),
topRight: _vec.set( _maxTarget.x, _maxTarget.y, - distance ).applyMatrix4( camera.matrixWorld ).clone(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would return values in camera space - not world space. topRight, topLeft, have no meaning once the camera is rotated.

Copy link
Collaborator

@Mugen87 Mugen87 Jan 18, 2024

Choose a reason for hiding this comment

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

It seems the tests developers usually perform with these coordinates happen in world space. If the vectors are now in camera space, users have to convert their data into camera space as well OR convert the frustum corner points to world space.

I wonder if this makes the workflow unnecessarily complicated.

We often compute bounding volumes in world space knowing they are only valid as long as the object does not move. I think we can make the same assumptions for the corner points as well.

Copy link
Collaborator

Choose a reason for hiding this comment

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

As I said, topRight, topLeft, have no meaning in world space. Return the values in camera space. Any user using this method knows how to convert a point from camera space into world space -- if that is what they want.

Copy link
Contributor Author

@Bug-Reaper Bug-Reaper Jan 18, 2024

Choose a reason for hiding this comment

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

See it as a stretch to say topLeft fully looses all meaning if the camera is rotated? Agnostic of camera rotation or reference coordinate space, the topLeft vector will still be the point that is rendered to the topLeft of the screen.

Agree that if we return the results in camera-space it blunts the utility meant to be added here. Think world-space is the right play and that the nature of the top/bottom/left/right is still easily apparent.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In addition to my previous comments, I do not think .getFrustumBounds() and .getFrustumCorners() should return results in different coordinate frames.

And I agree, .getFrustumCorners() provides little added utility.

Copy link
Collaborator

@Mugen87 Mugen87 Jan 19, 2024

Choose a reason for hiding this comment

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

@Bug-Reaper To avoid an impasse here, I suggest you remove getFrustumCorners() from this PR and create a separate one. In this way, we can at least get the changes to PerspectiveCamera merged now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay guys, gonna remove getFrustumCorners() from this PR so we can get the goods merged ⭐️

I do believe there's tangible utility added from a method that returns the corners in world-space. Perhaps the name conventions can be improved to clearly indicate the functionality. Will take the feedback from this discussion to heart and try to keep it in mind when I get a chance to do a seperate PR for this method.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 18, 2024

Made these review upgrades 🦾 plan to commit doc updates to match with the changes shortly

I've added a few commits to the branch to honor the latest feedback. The API in PerspectiveCamera looks ready to go!

We can now focus on CameraUtils.getFrustumCorners().

@Mugen87 Mugen87 changed the title 🎥 : PerspectiveCamera : New helper methods getBounds(), frustumDimensions(), frustumCorners() 🎥 : PerspectiveCamera: New helper methods getFrustumBounds(), getFrustumSize(), getFrustumCorners(). Jan 18, 2024
@Bug-Reaper Bug-Reaper changed the title 🎥 : PerspectiveCamera: New helper methods getFrustumBounds(), getFrustumSize(), getFrustumCorners(). 🎥 : PerspectiveCamera: New helper methods getFrustumBounds(), getFrustumSize(). Jan 19, 2024
@Bug-Reaper Bug-Reaper force-pushed the feature/get-margin-at branch from 71544c6 to c9f5641 Compare January 19, 2024 15:58
@Mugen87 Mugen87 merged commit 668968e into mrdoob:dev Jan 19, 2024
12 checks passed
@WestLangley WestLangley changed the title 🎥 : PerspectiveCamera: New helper methods getFrustumBounds(), getFrustumSize(). PerspectiveCamera: New helper methods getFrustumBounds(), getFrustumSize(). Jan 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants