Jump to content
  • Advertisement
Sign in to follow this  
Gamer Pro

How to fit a box in the camera's view frustum

This topic is 2089 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

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



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



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).

Edited by Gamer Pro

Share this post

Link to post
Share on other sites
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.

Share this post

Link to post
Share on other sites

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?

Edited by Gamer Pro

Share this post

Link to post
Share on other sites
Tan(105/2) = 1.3 and 1.3 x 818 is 1063, close to your edge of screen, so that all seems to fit.

I can't see where your distances come from. I can only assume a calculation error.

Share this post

Link to post
Share on other sites

It was a calculation error, instead of using tan I was using atan dry.png


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).

Edited by Gamer Pro

Share this post

Link to post
Share on other sites

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.


// Calculate box's dimensions after rotatations.
vector dimensions = box dimensions
matrix rotation = elevation rotation * heading rotation // XYZ euler order.
dimensions = dimensions * rotation
// Figure out how to size box so all if it fits in view.
horizontalPercent = dimensions.x / screenX
verticalPercent = dimensions.y / screenY
// Calculate distance.
if horizontalPercent > verticalPercent then
  opposite = dimensions.x / 2
  distance = opposite / tan(horizontalFoV / 2)
  opposite = dimensions.y / 2
  distance = opposite / tan(verticalFoV / 2)
// Distance lets me see entire box if side is at origin, box is centered on origin so add half its depth.
distance = distance + dimensions.z / 2
// And create camera....


Step 2, figure out where the rendered box's center is


// Because the entire box fits on screen, I can calculate each corner's Normalized Device Coordinates.
For each corner
  point = projectPointToScreen(point)
  // update the max and min x & y values.
centerX = (maxX + minX) / 2
centerY = (maxY + minY) / 2


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.


Any ideas?

Edited by Gamer Pro

Share this post

Link to post
Share on other sites
I suspect it is because you are rotating the box dimensions rather than calculating the size of the box along the axis.

Find the box axes and the camera x and y axes in world space. Then the size of the box along the camera x axis is:

Box size X * abs(dot(Box X, Camera X))+
Box size Y * abs(dot(Box Y, Camera X))+
Box size Z * abs(dot(Box Z, Camera X))

And equivalently for y.

Share this post

Link to post
Share on other sites

+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'.

Share this post

Link to post
Share on other sites
It's a triangle problem, and the triangles happen to be in 3D, but the maths is the same.

Screenshots? I can't visualise what the problem is.

Share this post

Link to post
Share on other sites

Heading: 0°, elevation 0°

[attachment=13751:0 heading, 0 elevation.png]


Heading: 90°, elevation 0°

[attachment=13752:90 heading, 0 elevation.png]


Heading 0°, elevation 90°

[attachment=13753:0 heading, 90 elevation.png]


Heading 90°, elevation 90°

[attachment=13754:90 heading, 90 elevation.png]


Heading 45°, elevation 45°

[attachment=13755:45 heading, 45 elevation.png]


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.

Edited by Gamer Pro

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!