25.4 Converting real coordinates to pixel positions

As mentioned before, many of the most interesting kinds of computer graphics are based on equations, drawn from mathematics, and physics. These equations are normally stated in terms of vectors and real numbers. In order to depict images and motions based on mathematics and physics we need to be able to translate back and forth between mathematical cVector positions and CPoint pixel locations in an onscreen window.

Windows has some GDI functions of the form SetMapMode and SetViewport that are useful in converting between different integer-valued sizes of windows. This is the kind of thing you need to do in, for instance, desktop-publishing when you want to control the physical sizes of printed versions of the images on the screen. But Windows does not have any built-in functions for converting between real numbers and pixels. The author has developed a cRealPixelConverter class for this purpose. By the way, Java comes with a somewhat similar class called Transformation built in, though not with all of our special methods supplied. And when you do OpenGL graphics, the transformation from real to pixel coordinates is something that the OpenGL graphics pipeline does for you automatically, with the settings being controlled by your calls to the ::glViewport method.

Here are the steps for using a cRealPixelConverter. If you want to see the details of the implementation, look in the realpixelconverter.h and realpixelconverter.cpp files.

  • Declare a cRealPixelConverter object in a line like

    cRealPixelConverter _realpixelconverter 

    Since our View windows are going to have different sizes, it makes sense to have a dedicated converter for each view.

  • Tell your cRealPixelConverter the size of the Real window that you plan to use for the world in which your cVector values are going to live. This might be done in CPopView::OnCreate, with a line like

    _realpixelconverter.setRealWindow(lox, loy, hix, hiy). 
  • Tell your cRealPixelConverter the size of the pixel window that you are going to be displaying your objects in. We always resize the cRealPixelConverter 's pixel window to match the current size of the onscreen window. This is done by adding a line of code to the view's OnSize message handler.

    Your view's OnSize(UINT nType, int cx, int cy) method gets called (i) at startup, (ii) when you resize the view window by dragging on of its edges, and (iii) when you use the buttons at the View window's upper right-hand corner to minimize, maximize, or return to normal size. The nType variable tells you if the window's being maximized, minimized, or resized and the cy and cy tell you the size of the window's new client area. To tell _realpixelconverter to match its pixel window to the newly resized screen window, we use code like this. Note that we go ahead and call the base class OnSize function first; in general this is the correct and safe thing to do when you override the handling of a standard message.

    void CView::OnSize(UINT nType, int cx, int cy) 
        CView::OnSize(nType, cx, cy); 
        // TODO: Add your message handler code here 
        _realpixelconverter.setPixelWindow(cx, cy); 

    In the Pop framework, we allow for the different graphics implementations cGraphicsMFC and cGraphicsOpenGL, both derived from cGraphics. So our CPopView class has a cGraphics *_pgraphics member, and the actual Pop Framework CPopView::OnSize method calls _pgraphics->setViewport(cx, cy). A cGraphicsMFC object has a cRealPixelConverter member, and the cGraphicsMFC::setViewport code invokes this member's cRealPixelConverter::setPixelWindow method.

    void CPopView::OnSize(UINT nType, int cx, int cy) 
        CView::OnSize(nType, cx, cy); //Machine code. 
        _pgraphics->setViewport(cx, cy); 
            //width/height ratio 
  • For each object that you want to display, use your cRealPixelConverter's realToPixel function to convert the real number coordinates of the object into pixel coordinates. In the Pop Framework's graphicsmfc.h there are examples of this in lines like

    _realpixelconverter.realToPixel(center.x(), center.y(), 
        &intx, &inty); 
  • If you need to convert a real number length into a pixel window length use the cRealPixelConverter::realToInt method.

  • If you need to turn a window coordinate such as a mouse click location into a real number location, use your cRealPixelConverter::pixelToReal method. In the Pop Framework's graphicsmfc.h, the cGraphicsMFC::pixelToVector does this with a line like

    _realpixelconverter.pixelToRealintx, inty, 
        &realx, &realy); 

    Part I: Software Engineering and Computer Games
    Part II: Software Engineering and Computer Games Reference