# rubberband zoom

I want to implement a rubberband box zoom feature in my 3D openGL window, but am having problems.

I can create/draw the rubberband itself. Next, I need to make the contents of this rubbberband box become 90% of the window (only 90% because I want a small buffer on all sides). I’m having trouble conceptualizing how to do this. Any thoughts?

You could try doing something sneaky with gluPickMatrix. Set your viewport (glViewport) to the rectangle of your zoom inset, then call gluPickMatrix (before glOrtho/glFrustum) with the center of the rect and the width and height of the inset (gluPickMatrix multiplies a matrix onto the projection matrix stack that stretches the pick rectangle so that it covers the entire viewport.)

I haven’t tried this with gluPickMatrix specifically, but I think it should work in principle.

caveman, thanks for the suggestion. I’ll give it a shot.

Well, I’ve had quite a bit of free time lately (perhaps too much), so I threw together a little utility function for this sort of thing.

``````/* Call ZoomMatrix on the projection matrix stack before applying your normal
* projection transformation (like gluPickMatrix).
*
* zoom{X,Y,W,H}:
*		the zoom origin and dimensions in the main viewport
*		(symmetric rectangle centered at (X,Y))
*
* dest{W,H}:
*		the destination width and height in the main viewport to render the zoomed scene in
*		(call glViewport with this rectangle)
*
* viewport{W,H}:
*		the width and height of the main viewport
*/
void ZoomMatrix(float zoomX, float zoomY, float zoomW, float zoomH,
float destW, float destH,
float viewportW, float viewportH)
{
float scaleX = destW / viewportW;
float scaleY = destH / viewportH;
zoomX *= scaleX; zoomY *= scaleY;
zoomW *= scaleX; zoomH *= scaleY;
glTranslatef((destW - 2 * zoomX) / zoomW, -(destH - 2 * zoomY) / zoomH, 0);
glScalef(destW / zoomW, destH / zoomH, 1);
}
``````

Edit: Oops, forgot to remove the redundant parameters.