# Programming 2D Computer Graphics

*In This Chapter*

**Understanding Screen and Cartesian Coordinates****Defining Vertex and Shape Data Types****Transforming Shapes****Using Matrix Math in Transformations****Building a 2D Graphics Application****Running the Graphics2D Application****Understanding How the Graphics2D Program Works****Exploring the Program Listings****In Brief**

As you've learned, Direct3D provides many powerful functions for creating 3D graphics on your computer. These functions hide many programming details that must be dealt with to produce sophisticated graphics. Still, to understand Direct3D, you need to have a little background in standard 3D programming practices. The first step toward that goal is to understand how your computer programs can manipulate simpler 2D images.

This chapter, then, introduces you to the basics of 2D graphics programming, including the formulas needed to transform (move, rotate, scale, and so on) 2D shapes in various ways. Although transforming 2D shapes requires that you know a set of formulas for manipulating the points that define a shape, you'll discover that these formulas are easy to use, even if you don't really understand exactly how they work.

In this chapter, you learn:

About screen and Cartesian coordinates

About using vertices to define 2D shapes

About translating, scaling, and rotating 2D shapes

How to use matrices to transform 2D shapes

## Understanding Screen and Cartesian Coordinates

Undoubtedly, you have at least some minimal experience with drawing images on
a computer screen under Windows. For example, you probably know that to draw a
line in a window, you must call the GDI function `MoveToEx()` to position
the starting point of the line and then call the function `LineTo()` to
draw the line. In a program, those two function calls would look something like
this:

MoveToEx(hDC, x, y, 0); LineTo(hDC, x, y);

The arguments for the MoveToEx() function are a handle to a device context (DC), the X,Y coordinates of the point in the window to which you want to move, and a pointer to a POINT structure in which the function should store the current position before moving to the new position. If this last argument is 0, MoveToEx() doesn't supply the current position. The arguments for the LineTo() function are a handle to a DC and the X,Y coordinates of the end of the line.

Of interest here are the X,Y coordinates used for the end points that define
the line. Assuming the default mapping mode of `MM_TEXT`, both sets of
coordinates are based on window coordinates, which, like normal screen coordinates,
begin in the upper-left corner of the window, with the X coordinate increasing
as you move to the right and the Y coordinate increasing as you move down. Figure
3.1 shows this coordinate system.

**Figure
3.1 A window's MM_TEXT coordinate system.**

Most computer programmers are familiar with the coordinate system shown in
Figure 3.1. Unfortunately, most objects
in computer graphics are defined using the *Cartesian* coordinate system,
which reverses the Y coordinates so that they increase as you move up from the
origin. Also, as shown in Figure 3.2,
the Cartesian coordinate system allows negative coordinates. If you remember
any of your high school math, you'll recognize Figure
3.2 as the plane on which you graphed equations. In computer graphics, however,
you'll use the Cartesian plane as a surface that represents the world in
which your graphical objects exist.

**Figure
3.2 The Cartesian coordinate system.**

You define graphical objects in the Cartesian coordinate system by specifying
the coordinates of their *vertices*, which are the points at which the
lines that make up the object connect. For example, a triangle can be defined
by three points, as shown in Figure 3.3.
The defining points in the triangle are (2,5), (5,2), and (2,2).

**Figure
3.3 Defining a triangle in the Cartesian coordinate system.**

A problem arises, however, when you try to draw an object defined in the Cartesian coordinate system onscreen. As you can see by Figure 3.4, the figure comes out upside-down due to the reversal of the Y coordinates in the screen's coordinate system as compared with the Cartesian coordinate system. The C++ code that produces the triangle looks like this:

MoveToEx(hDC, 2, 5, 0); LineTo(hDC, 5, 2); LineTo(hDC, 2, 2); LineTo(hDC, 2, 5);

**Figure
3.4 Drawing a triangle with no mapping between the Cartesian
and screen coordinate systems.**

Because of the differences between a screen display and the Cartesian
coordinate system, you need a way to translate points from one system to the
other. In graphics terms, you must *map* points in the Cartesian coordinate
system to points in the screen coordinate system so that objects you draw
onscreen are positioned correctly. Forgetting about negative coordinates for the
time being, mapping point (x1,y1) in the Cartesian coordinate system to point
(x2,y2) in the screen coordinate system requires the following simple formulas,
shown in C++ program code:

x2 = y1; y2 = maxY - y1;

Because the X coordinate is unaffected by the mapping, x2 is simply assigned the value of x1. To reverse the Y coordinate, the original Y coordinate is subtracted from the window's maximum Y coordinate. Of course, for this formula to work, you must know the current size of the window. You can get this value by calling the Windows API function GetClientRect(), which fills a RECT structure with the size of the window's client area. Listing 3.1 draws a triangle in the window, mapping between the Cartesian coordinates and the screen coordinates.

#### Listing 3.1 Drawing a Triangle

int triangle[6] = {2, 5, 5, 2, 2, 2}; int newX, newY, startX, startY; RECT clientRect; GetClientRect(hWnd, &clientRect); int maxY = clientRect.bottom; for (int x=0; x<3; ++x) { newX = triangle[x*2]; newY = maxY - triangle[x*2+1]; if (x == 0) { MoveToEx(hDC, newX, newY, 0); startX = newX; startY = newY; } else LineTo(hDC, newX, newY); } LineTo(hDC, startX, startY);

(Note that the preceding code segment is not complete and will not run on your computer. Later in this chapter, you develop a complete Windows program that demonstrates the topics discussed in this chapter.)

In the preceding code, the first line defines an array that contains the
Cartesian coordinates of the triangle. The variables `newX` and
`newY` will hold the screen coordinates for a point, and the variables
`startX` and `startY` will hold the screen coordinates for the
first point in the triangle. The `RECT` structure, `clientRect`,
will hold the size of the window's client area.

After declaring the local variables, the code calls `GetClientRect()`
to fill in the `clientRect` structure, at which point the
structure's `bottom` member will hold the height of the
window's client area. The code assigns this value to the local variable
`maxY`.

A `for` loop then iterates through the triangle's coordinate
array. Inside the loop, the currently indexed X,Y coordinates are mapped from
Cartesian coordinates to screen coordinates. The first mapped point is used to
set the starting point of the triangle. The code uses subsequent points to draw
the lines that make up the triangle. The call to `LineTo()` outside the
loop connects the last point of the triangle to the first point.