Sign in to follow this  

Center Camera on Object

This topic is 3852 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have an object loaded (and its associated bounding box). I also have a camera. I can retrieve a full matrix describing its orientation. I can also retrieve its field-of-view value (a single scalar). My goal is to position the camera so that it is looking straight at the object, the object is fully visible, and the object takes as much space on screen as possible. That is, I want a 'tight fit' around the object. I've tried various trig approaches, but they don't seem to be working properly. Any insights would be appreciated. Cheers, --Brian

Share this post


Link to post
Share on other sites
This is not exactly what you are looking for but it may help. If the radius of the bounding sphere of the object is r, then
    z = r / sin( f/2 )
or
f = 2 sin-1( r/z )
where f is the fov and z is the distance to the object.

Share this post


Link to post
Share on other sites
You can build a new view matrix given a position to look at (in this case the position of your object) and a vector that describes the "up" direction of the camera.

Here's some pseudocode of how I do it in my own graphics code:

function lookAt(vector targetPosition, vector up)
{
// We need 3 vectors which we'll use to build an orthonormal vector
vector lookDirection;
vector upDirection;
vector right;

// Normalize the up vector
up = normalize(up);

lookDirection = normalize(targetPosition - cameraPosition);
right = cross(up, lookDirection);
upDirection = cross(lookDirection, right);

// Substitute into our view matrix
viewMat.row0 = right;
viewMat.row1 = upDirection;
viewMat.row2 = lookDirection;
}



You need to recalculate the up direction based on the right and look vectors because the up vector given may not be perpendicular to the look vector, so we calculate the cross product of the right vector and look vector to get a new up vector which lies on the same plane as the look and given up vectors.

Share this post


Link to post
Share on other sites
John,
Thanks, that works much better. Little disappointed in myself that I didn't see that property. ^_^
It does seem zoomed out a bit too much, though. I guess as a result of the bounding sphere being too large?
I calculate my bounding sphere radius by taking a point on the corner of the bounding box and finding its distance to the center.
Is there something better I could be doing?

Cheers,
--Brian

Share this post


Link to post
Share on other sites
Quote:
Original post by Nairb
John,
It does seem zoomed out a bit too much, though. I guess as a result of the bounding sphere being too large?
I calculate my bounding sphere radius by taking a point on the corner of the bounding box and finding its distance to the center.
Is there something better I could be doing?


That will work but it doesn't guarantee a tight fit. It all depends on the shape of the object and how tightly the bounding box fits it.

Just in case... in this case, fov is measured from one side to the other, not from the center to the side.

Also, the bounding sphere guarantees the object will not be clipped regardless of its orientation, but you can do better than that. The best fit is done by projecting the object into screen space, computing a bounding rectangle, and using that to determine distance or fov.

Share this post


Link to post
Share on other sites
I figured as much.

Could you possibly elaborate on how to use the bounding rectangle to compute the distance? I can onvert the object to screen space, but I'm not sure where to go from there.
Would I find the raduis around that box, convert this value back to space coordinates, and then use that instead? That doesn't feel right to me.

Thanks a lot so far,
--Brian

Share this post


Link to post
Share on other sites
I guess the easiest way is to figure out which vertexes are farthest from the center of the view and set set your FOV using those. In other words:
    maxX = 0
maxY = 0

for each vertex
transfrom vertex into view space
maxX = max( maxX, |x/z| )
maxY = max( maxY, |y/z| )

if ( maxX > maxY * aspect_ratio )
fov = 2 * tan-1( maxX/aspect_ratio )
else
fov = 2 * tan-1 maxY
Note: This assumes that the aspect_ratio is x/y and the the FOV is measured between the top and bottom of the screen.


Share this post


Link to post
Share on other sites

This topic is 3852 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this