codersnotes

Projected area of an AABB October 15th, 2009

I recently had the need to work out how much space an AABB takes up on screen, and I couldn't find any easy method for doing so.

People generally use spheres for this kind of stuff, which are a lot easier, but tend to be wildly inaccurate if the object isn't spherical. However it turns out that the AABB solution is in fact fairly trivial, so there's not much reason not to use it.

So here's what I came up with. I'm sure the Internet will tell me how this was done years ago in Graphics Gems 36, or by some mathematician back in the 16th century, or how I suck for struggling over something so trivial, but whatever.

The first part calculates how much area is visible when projected in a direction:
float projectedArea(float3 viewDir, float3 boxMin, float3 boxMax)
{
	float3 size = boxMax - boxMin;
	return dot( abs( viewDir ), size.yzx*size.zxy );
}
This assumes an orthographic projection within the object, so it doesn't take internal perspective into account, but for the kind of things I'm using it for (e.g. LOD calculation), it doesn't matter. There's only really a difference when it's close to the camera; when it's far away they're close enough.

Then you can use it for LOD calculations like so:
float lodValue(float3 viewPos, float3 objectPos, float objectArea)
{
	float d = distanceSquared(viewPos, objectPos);
	return objectArea / d;
}
Also, note that it's usually a good idea to scale the final value by the [0,0] value of your projection matrix, to account for the field of view of the camera.

Addendum: I feel I should point out that I'm using HLSL-style notation, and also that viewDir should be normalised.

Written by Richard Mitton,

software engineer and travelling wizard.

Follow me on twitter: http://twitter.com/grumpygiant