Does anyone know how to calculate pixel count quickly?

I found a tool class in JME – AreaUtils.class. When calculating the bounding sphere, the following formula is used: radius = (bound.getRadius() * screenWidth) / (distance * 2); pixel = radius * radius * FastMath.PI;. But I don’t know why this formula works. I think we should use the following formula: radius = (bound.getRadius() * cot(fov / 2) /distance; pixel = radius * radius * FastMath.PI;.
Does anyone know what this is about?

Any formula that’s calculating the on-screen pixel area of something and isn’t looking at the projection matrix is going to be wrong, I guess.

In my atlas generator stuff, I use m11 to push the camera in/out for to obtain a particular pixel to unit size… I imagine calculating the area from bounds + distance would involve the reverse in some way:

Edit:

But to me, it does provide some insight into why this is supposed to work:

…it’s just calculating that value manually. And it’s calculating the area of a circle.

I don’t think the radius should be calculated this way, the formula should be :radius = bound.getRadius() * cot(fov / 2) * screenWidth / distance; . And of course that’s the maximum radius, but it establishes an upper bound.

cot() of anything fov related is going to be vertical but you are using it to multiply width with no consideration for aspect ratio. So I think it can’t be right.

Presuming the distance is the projected distance along the eye vector, the foreshortening will be a constant. size = distance / ‘foreshortening’

…my memory says that ‘foreshortening’ is m11 in the projection matrix.

screenRadius = boundsRadius / proj.m11

Edit: but I admit my projection matrix fu is very rusty and I’d normally just try it until it worked.

Edit2: this may or may not be useful:
https://www.euclideanspace.com/threed/rendering/opengl/index.htm

…not as clear as the articles I read years ago, though.

I noticed that Ogre seems to do this:
ogre - Estimate pixel count

Jme seems to do this:


It doesn’t look the same?

There is no doubt that JME’s util method is wrong… it works only for a very specific projection matrix, I guess.

Ogre’s seems a little dodgy as well. I get that they are trying to deal with non-square pixels by using m00 and m11 but the / distanceSquared bit seems odd. Ah, I see… they are combining the x and the y together. So /2 becomes /4 (x 0.25) and /distance becomes /distanceSquared.

rx = (w/2) * m00 / distance;
ry = (h/2) * m11 / distance;
screenArea = rx * ry;

And I now see I forgot to include distance in my previous post.

So:
screenRadius = boundsRadius / proj.m11
Should have been:
screenRadius = boundsRadius / (proj.m11/distance)
Or:
screenRadius = boundsRadius * proj.m11 / distance
screenArea = screenRadius * screenRadius * PI
…which I guess is the square pixel version of what Ogre is doing.

1 Like

Yeah, I think so. I always thought it was the pixel count of the bounding sphere.

1 Like

Please open an issue on jme’s github repo if you’ve determined this code to be wrong

2 Likes