Hey guys, I'm having a problem with some basic math for a basic concept.

Idea:

I have a rectanglar box in my scene and I want to distance the camera such that the box just fits.

Background:

So right now I have my camera set up so that I can select a heading and an elevation. The software then calculates the camera's position using that data as if the camera is connected to a piece of string attached to the middle of the cube, tethering it to a spherical area. EG: I give it a heading of 45 degress and an elevation of 30 degrees, the camera is positioned 'Southwest' of the cube so it's looking 'Northeast' (45 degrees) and has an elevation of 30 degrees from the ground. If I give it a heading of 180 and an elevation of 90, the top of the screen is 'South' and the camera is directly above the box. (The x-axis is East/West, the y-axis is North/South). Now I'm trying to figure out to calculate the distance the camera needs to be so the box fills the screen. I know how to calculate the distance the camera needs to be so that no matter how the cube is rotated it fits (distance = boundRadius / sin(FOV / 2)). The problem with this is that the box is a wide, narrow rectangle, with little depth so using this method the box fills the screen only at a specific heading and elevation, otherwise there is a lot of empty space.

Current idea:

Since, ultimately, there's no difference between positioning the camera and rotating the mesh, I can think of the camera as being stationary and the mesh is being rotated so it's displayed with the correct heading and elevation. I was thinking that if I calculate the width and height of the box after it's rotated I can use trigonometry to calculate the distance (distance = halfWidth / tan(FOV / 2)). (If there's an easier/better idea, by all means, please let me know). I know how to calculate a 2D square's height and width after a 1D rotation, but I don't know how to calculate a 3D box's height and width after a 2D rotation.

What I know:

The box's height, width and depth; the camera's field of view, elevation (IE: x-axis rotation) and heading (IE: z-axis rotation).

It's the same principle in 2D or 3D. I'll assume you have a rotation matrix, so after you rotate the box, you have three vectors for the three axes. Take the dot product of each one with the direction you want, multiply by the size of the box on that axis and add them together.

Thanks for the responce EWClay, I found out that the API I'm using can be set up to calculate this for me but I appreciate the answer.

But now I have a math problem. My trigonometry isn't working.

My box's dimensions are: 1213, 623, 21; I have the heading at 0° and the elevation at 90° so the camera is giving me a bird's eye view with North to the top of my screen (IE: there's no rotations). My vertical field of view is 60°, the area I'm rendering to is 1920x850, which calculates my horiztonal field of view to be 105° (2 * atan(tan(FIELD_OF_VIEW_RADIANS / 2) * aspectRatio)). I use: distance = halfDimension / tan(FOV / 2) for both vertical and horizontal dimensions which gives me 646 & 818, respectively. Now this tells me that I need to position my camera 646 units away to fit the cube's vertically and 818 units away to fit the cube horizontally. I choose horizontally (so that the entire cube is visible). This should be right, right?

The problem is that if I position my camera 818 units away the cube is smaller than the frustum. The cube is centered on the origin and on my screen, so the above math (assuming it's right) states that the very right of my screen is 606.5 positive units on the x-axis, making the cube just fit horizontally. However I can place a small cube at 1065 units on the x-axis and it's on the edge of my screen (I just picked numbers till the cube was just on my screen).

I've looked over my math and it looks right. Maybe I'm missing something? Could their be something about the perspective camera I didn't take into account?

But I think my solution is flawed. Lets ignore the above example and work with this one. Both heading and elevation is 0°, this makes my box's dimensions 1213, 21, 623. I'm choosing to fit the box horizontally. The opposite side is half x (606.5) and my half FOV is 52.5° (from the calculated horizontal FOV of 105°). distance = opposite / tan(halfFOV) = 465.

Now the math is right but the fustrum is too small and part of the cube is outside of it.

* Edit

I found out what my problem is. I'm calculating how far FROM THE ORIGIN the camera needs to be to fit something so wide/tall in it's frustum, I forgot to acount for the box's width/height (well, half width / half height).

Alright final question. I have everything setup, I have 1 last thing to do. I want to maximise the box in my view (it's not as easy as it sounds). Insofar, I have my camera creation broken down into 3 steps (if I'm doing anything wrong or weird feel free to set me straight). Here's my pseudo code.

Step 1, I initialize the camera such that the entire box is in my viewing frustum.

Step 3, figure out where in world space the rendered box's center is and look at that.

camera.lookAt = projectPointToWorld(centerX, centerY)

Now this works great; the box is perfectly centered on screen and when I'm looking straight down (elevation = 90) the box is maximised. But if I'm looking at it at an angle (elevation != 90) there is space on the top and bottom of it. I would like to calculate the camera distance so that the box is maximised. I'm not sure how to do that that and it would have to be back in step 1; because if I move the camera closer (or further) then the gap at the bottom of the box is going to close quicker than the gap at the top (due to perspective) and the box is no longer centered in my view.

+1 for the proper way to calculate the box's dimensions (I have no idea why I didn't think of that), but that wasn't my problem; I'm still calculating distances that are too big in the end. It must be my trig? Maybe it's more complicated than simply thinking of it as a 2D problem, after all it's the 3rd D that's causing my persepective 'issue'.

As you can see the edge cases work but not the middle. Which kind of makes sense if you think about it, at the edge cases the box is perpendicular to the camera and everything is great.

(Grey is box, orange is camera, red is distance)

But in the middle cases, the box is no longer perpendicular to the camera and gaps are introduced. Not only that but the distance isn't the same.

(Grey is box, orange is camera, red is distance if the camera was perpendicular, pink is actual distance and black is gaps introduced from the box's rotatation).

The black gaps aren't an issue since I'll be moving the camera closer and therefore eliminate them; however the trig I'm using is assuming I'm perpendicular to the box. So the distance I'm calculating is the red line but I'm applying it to the pink line.

I don't understand how their can be 2 sizes. Do you mean the 'starting' and 'ending' point of the box & therefore using those points to determine the box size? Wouldn't the above forumla do that for me so D = halfDepth * sin(half FOV) (I'm assuming I'm multiplying, you missed the operator in your post.)

Do the same for left and right.

This is so I can determine if I should be sizing vertical or horizontally, right?

You'll need to pan the camera to make it fit.

I'm currently doing this by determining the center of box when it's rendered on screen and finding that point in the world. I like your way better since the code is much smaller (the most efficent code is the one you don't write, afterall). But I need clarification on the sizes thing.

Okay, I've calculated the distance. It works for the 90° cases and for the middle cases it looks right (I won't know until I complete the panning). But I do have a couple of questions regarding the panning.

For the panning distance, I'm going: size calculated from the top normal - size calculated from the bottom normal & size calculated from the left normal - size calculated from the right normal. Is that correct or should they be the other way around?

Finally, I have no idea how to calculate the vector I need to pan along so that box fits and is centered.

And thank you for all the help; I've been trying to figure this out for a few months now and all the progress I've made in the last month has been directly because of you.

The formula gives you horizontal and vertical panning distances (camera x and camera y). You have it the right way round and combining the two components gives the vector to move along.

For the one that fits exactly you should pan the full distance in the respective direction. For the other direction I'd guess you should scale it down by the ratio of the distances, but I haven't worked that through.

Also, note that the panning distance is signed and this tells you which way to go along each axis.

So I've calculated a horizontal panning distance of 147 and a vertical panning distance of -448. So this means I need to pan along the camera's x-axis 147 units to the right and along the camera's y-axis 448 units down (first flag, it looks like I should be panning to the left, not the right). I calculate the normalized vectors that represent the camera's x and y-axis and multiply those vectors with the corresponding magnitudes and now I have the world coordinates.

Question, when you say pan do you mean move the camera? That's what I think when I hear pan. The problem with this is that the camera is positioned such that it is viewing the box at the given heading and elevation, if I move the camera this is now no longer the case. IE: The camera is something like 545 units up in the air as part of the 45° elevation, if I move the camera down the world version of 448 units, the camera is know, like, 15° elevated. The above picture is the camera LOOKING AT the calculated world coordinates of (147, -448).