tags:

views:

1333

answers:

2

I have an OpenGL application which implements navigation functions such as Orbit, Walk, Pan, Rotate, etc. for navigating a 3D environment. All this works flawlessly and is fairly straighforward to set up using gluPerspective and gluLookAt.

glMatrixMode GL_PROJECTION
   glLoadIdentity
   gluPerspective m_ViewAngle, m_AspectRatio, m_ClipDistance_Near, m_ClipDistance_Far          

   glMatrixMode GL_MODELVIEW
   glLoadIdentity
   gluLookAt m_Eye.X, m_Eye.Y, m_Eye.Z, m_Focus.X, m_Focus.Y, m_Focus.Z, m_ViewUP.X, m_ViewUP.Y, m_ViewUP.Z

   glCallList DisplayListIndex

Similar to a typical ZoomExtents or ZoomToFit command in CAD software, from any arbitrary viewpoint (view direction), I would like to be able to zoom so that (1) The entire 3D environment is visible, and (2) The 3D environment model fills the entire viewport (is as large as possible given the current size of the viewport).

I know the bounding box (extents) of the environment (min XYZ, max XYZ). However, I have been unable to derive what the Eye and Focus positions should be for the given ViewAngle and AspectRatio and environment extents.

Perhaps there's an easier way to accomplish this, than with gluLookAt. Any help is appreciated!

A: 
eed3si9n
Using a sphere does NOT work. It guarantees the entire environment visible. However, this method does not make the environment as large as possible on the screen for all cases (e.g. when the bounding box size is X=10, Y = 10, Z = 2, and the viewpoint is from the side).
JRS
If that's your complaint, then axis-oriented bounding boxes are equally useless when viewing the scene from non-axis aligned directions. You would then need the convex hull of the scene.
Eric
JRS: I didn't understand your comment for a moment. I think you mean to say it would not work when the bounding box size is X=10, Y=2, Z=2, and viewed from the side.
Tartley
+1  A: 

Actually it can be done much 'easier'.

What you need to do is a projection of your model to a plane. Then, determine the highest and lowest points (top y, bottom y, leftmost x, rightmost x), and finally determine how much scaling you need to fit this rectangle in the rectangle you'd actually need.

The plane you need to project on is the screen plane.

Luckily for you, you are already doing this.

So, transform every point of your model using the matrices you already have set, and determine the maximum points.

Calculate how much scaling you'd need to fit it on the screen. And apply this scaling to the zoom of the object

Thats it

Toad
Am I right in thinking that when you say 'you are already doing this', what's actually happening is that OpenGL is doing it for him? I don't know how to get access to the results of those calculations. Is that easy? If not, to implement this, he'll need to replicate the matrix/vertex arithmetic in his own code: Take the PROJECTION and MODELVIEW matrices, multiply them by every vertex in his model, etc. A shortcut would be to just perform this same calculation on the entire model's bounding box, instead of every vertex in the model.
Tartley
Ah. The bounding box shortcut is clearly not adequate, given JRS's comments on other answers to this question.
Tartley