Best way to calculate the percentage of an object shown in a camera frame?

Hey community,

Just wondering, what is the best way to calculate how much percentage of an object shown in a camera frame?

For example:
(Images below are from Maya viewport)


If an object fills up the entire camera frame from top to bottom, I hope there could be a “visibility factor (vertical)” to indicate the showing status. In the image above, the sphere is showing 100% vertically and also occupied the exact full camera frame top down. So this factor could consider as 1 in vertical direction.

And if the camera zoom further, the factor could be a value greater than 1, such as ~2.1 in the image below:

And if the camera zoom all the way into the object, it could be a factor between 0 and 1:

If zoom to as close as one vertex, the factor could be a very small positive float number almost equals to 0.

Of course, this whole idea could use bounding box points instead of actual vertex from the mesh to reduce the calculation load.

I figured out a way to detect if an object in completely inside of camera frustum (or a region of camera frustum) or not:

(PS: This PG derived from this great topic: https://forum.babylonjs.com/t/check-isinfrustum-but-with-a-percentage-of-the-camera-view/16906`)

I feel like I kind of started getting this idea working but not as accurate as I was expecting.

Does anyone have a better idea?
Many thanks,
Tawibox

I think it’s the right way to do it, to compute the part of the bounding box which is inside the screen. Maybe it would be a little easier by doing the computation in 2D, though, by projecting the bbox to the screen.

1 Like

@Evgeni_Popov

Thanks for the response!

Does babylon has a way to compute the pixel the bbox projecting to the screen?
Can you provide more details about it?

Many thanks,
Tawibox

Oh I think I found it. Is it vector3.Project?

https://doc.babylonjs.com/typedoc/classes/BABYLON.Vector3#Project

Yes ! :slight_smile:

I knew soon I will have to do this (3D projection to 2D local) so here we are :

  • 3D Local (mesh) :arrow_right: 3D Global (world)
  • 3D Global :arrow_right: 2D Canvas (project)
  • 2D Canvas :arrow_right: Bounding Box (min/max)
    Playground

Have fun ! :slight_smile:

++
Tricotou

4 Likes

@Tricotou

Wow that’s exactly what I am looking for!!

Thank you so much!!

This is an awesome trick. Bookmarked! I love this community, lot of cool techniques out there always learn something new!

1 Like

Hey @Tricotou I have a follow up question.

If I just want to do this calculation only once instead of do it on every frame at run-time, how should I do it? For example, when I load in a gltf with animation, I just want to go a certain frame to do the calculation to get the “framing factor” on that particular frame. How would I do it? Can you provide a PG example?

Or you can use my PG:

As you can see, in line 71 I am trying to print out the framing factor outside of rendering loop but got null.

I was trying to do it myself but no luck.

Many thanks!
Tawibox

The problem comes from the fact that, you are running it inside the createScene function, and even before it’s done. The scene is not fully ready. For example you can wrap it inside the scene.whenReadyAsync function to make sure it’s ok : Playground

2 Likes

@Tricotou
aha gotcha!! thank you so much!!!