Center Camera on Object

Started by
5 comments, last by JohnBolton 16 years, 11 months ago
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
Advertisement
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.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
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.
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
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.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
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
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.


John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!

This topic is closed to new replies.

Advertisement