I’m a newer to both the OpenGl and this forum. I need to generate static images of 3D objects. I set up the camera initially to make the camera direction parallel to the shortest moment of the object, so that the x/horizontal parallel to the longest. But in this way, after rotating the object around the y axis for 90 degree, the camera direction will parallel to the longest moment of the object, and the x parallel to the shortest, so that the object seen in the screen is very small.
Since I just need to generate static images, I’d like to enlarge reasonably the objects seen at any moments in images. I know I can change the FOV to get a zoom in/out effect, but how may I make code to change the FOV automatically? I have these data available: radius of the object itself, and of the bounding box, coords of both centers, the lengths of edges of the bounding box, coods of 8 vertices of the box.
You shouldn’t change the field-of-view angle, but the distance of the viewpoint from the object. The angle should be chosen according to the desired perspective. A value between 60 and 90 degrees (+/-30 to +/-45) is typical.
For a sphere, you need (r/d)<sin(a/2), where r is the radius, a is the field-of-view angle and d is the distance between the viewpoint and the centre of the sphere. For a box which is aligned to the view direction, you need ((s/2)/d)<tan(a/2), where s is the size of the box, a is the field-of-view angle, and d is the distance between the viewpoint and the face closest to it.
In each case, you need to calculate the appropriate distance for each direction (width and height), using the appropriate view (unless the viewport is square, the horizontal and vertical field-of-view angles will be different) and use the larger value. The viewport’s aspect ratio is the ratio of the tangents of the two angles; e.g. for a 16:9 display, tan(fovX)/tan(fovY)=16/9.
> For a sphere, you need (r/d)<sin(a/2), …, For a box which is aligned to the view direction, you need ((s/2)/d)<tan(a/2), …
About the sphere and the box, do you mean they are the bounding sphere and box of the entire object? If so, these are what I’m exactly doing that, as my previous post said, both of them are able to generate the best images when the x axis parallel to the longest moment, and camera direction parallel to the shortest moment of the object. But after a rotation, the object may look very small in the image.
> In each case, you need to calculate the appropriate distance for each direction (width and height), …
Sorry, I am not quite sure I understand well the “distance for each direction”. Do you refer it to the width of height of the XY plane? if so, I have the data. Do you mean that I have to pick up a larger one from such a width and height to use it as the s in the ( (s/2)/d ) < tan(a/2)? I tried, but it doesn’t always work well. If say, dt = tan(a/2) - ( (s/2)/d), it’s sort of hard to find an universal dt for all the moments of random objects.
To zoom in and out, you should be using the View matrix to dolly the camera closer to the object.
Changing the FOV doesn’t “really” zoom in and out. It does somewhat act like changing the focal length on a lens, but not really. What it’s really doing is more akin to setting the vanishing points in a 4 point perspective drawing or you can think of it as a two point perspective drawing if that helps. By bringing the vanishing points together, you increase the width of what can be seen by the camera. As they separate, you are decreasing what can be seen and what can be seen will take up more screen real estate. That would give something of a zoom effect. But you’re distorting the perspective when doing that similar to using a zoom lens. Going in the opposite direction will give you something like a fish-eye lens, also distorting the perspective.
This can happen if the bounding box or sphere are much larger than the object itself, i.e. the object is long and thin and the bounding box or sphere isn’t suitably aligned (or a bounding sphere is a sphere rather than an ellipsoid).
For finding the optimal allignment of a bounding box, PCA usually provides good results for significantly less overhead than the exact result.
The width and height of the viewport.
You need to ensure that the projected width of the object is less than the width of the viewport, and the projected height of the object is less than the height of the viewport. Each of those calculations gives you a distance; choosing the largest distance will ensure that the entire object fits inside the viewport.
When working with field-of-view angles, there are separate angles for the width and height. Assuming that you want the projection to preserve aspect, the ratio of the angles’ tangents should match the ratio of the viewport’s dimensions.
Also, you need to decide whether you’re trying to fit the object at a specific rotation to the viewport, or choose a distance such that you can apply any rotation and still have the object fit in the viewport.
For long, thin objects, the latter will result in it being very small when viewed end-on, while the former will result in the distance changing rapidly as the object is rotated. The former option is best achieved by fitting a bounding sphere (or cylinder, if you only need rotation about one axis) to the viewport.
Thanks so much GClements! Your reply really helped me to understand better now. Sorry for this late response.
When I said XY plane, I did mean the viewport. I have the size of the viewport in the pixel unit, and the width & height of the object in the object coordinate at a rotation. I realized that I had to use both information, but just didn’t know how to use them. Now the direction of solving my issue is clear to me, though I still need to look for methods to calculate the projected width and height of the object. I think I can find some online.
Yeah, I do want an image where the object at the specific rotation may fit to the viewport to the most extent.