Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Beginning iOS5 Development.pdf
Скачиваний:
7
Добавлен:
09.05.2015
Размер:
15.6 Mб
Скачать

564

CHAPTER 16: Drawing with Quartz and OpenGL

If a painter paints an entire canvas red, and then paints the bottom half of the canvas blue, the canvas will be half red and half either blue or purple (blue if the paint is opaque; purple if the paint is semitransparent). Quartz 2D’s virtual canvas works the same way. If you paint the whole view red, and then paint the bottom half of the view blue, you’ll have a view that’s half red and half either blue or purple, depending on whether the second drawing action was fully opaque or partially transparent. Each drawing action is applied to the canvas on top of any previous drawing actions.

On the other hand, OpenGL ES is implemented as a state machine. This concept is somewhat more difficult to grasp, because it doesn’t resolve to a simple metaphor like painting on a virtual canvas. Instead of letting you take actions that directly impact a view, window, or image, OpenGL ES maintains a virtual three-dimensional world. As you add objects to that world, OpenGL ES keeps track of the state of all objects.

Instead of a virtual canvas, OpenGL ES gives you a virtual window into its world. You add objects to the world and define the location of your virtual window with respect to the world. OpenGL ES then draws what you can see through that window based on the way it is configured and where the various objects are in relation to each other. This concept is a bit abstract, but it will make more sense when we build our OpenGL ES drawing application later in this chapter.

Quartz 2D provides a variety of line, shape, and image drawing functions. Though easy to use, Quartz 2D is limited to two-dimensional drawing. Although many Quartz 2D functions do result in drawing that takes advantage of hardware acceleration, there is no guarantee that any particular action you take in Quartz 2D will be accelerated.

OpenGL ES, though considerably more complex and conceptually more difficult, offers a lot more power than Quartz 2D. It has tools for both two-dimensional and threedimensional drawing, and is specifically designed to take full advantage of hardware acceleration. OpenGL ES is also extremely well suited to writing games and other complex, graphically intensive programs.

Now that you have a general idea of the two drawing libraries, let’s try them out. We’ll start with the basics of how Quartz 2D works, and then build a simple drawing application with it. Then we’ll re-create the same application using OpenGL ES.

The Quartz 2D Approach to Drawing

When using Quartz 2D (Quartz for short), you’ll usually add the drawing code to the view doing the drawing. For example, you might create a subclass of UIView and add Quartz function calls to that class’s drawRect: method. The drawRect: method is part of the UIView class definition and is called every time a view needs to redraw itself. If you insert your Quartz code in drawRect:, that code will be called, and then the view will redraw itself.

www.it-ebooks.info

CHAPTER 16: Drawing with Quartz and OpenGL

565

Quartz 2D’s Graphics Contexts

In Quartz, as in the rest of Core Graphics, drawing happens in a graphics context, usually referred to just as a context. Every view has an associated context. You retrieve the current context, use that context to make various Quartz drawing calls, and let the context worry about rendering your drawing onto the view.

This line of code retrieves the current context:

CGContextRef context = UIGraphicsGetCurrentContext();

NOTE: Notice that we’re using Core Graphics C functions, rather than Objective-C objects, to do our drawing. Both Core Graphics and OpenGL are C-based APIs, so most of the code we write in

this part of the chapter will consist of C function calls.

Once you’ve defined your graphics context, you can draw into it by passing the context to a variety of Core Graphics drawing functions. For example, this sequence will create a path consisting of a 4-pixel-wide line in the context, and then draw that line:

CGContextSetLineWidth(context, 4.0); CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); CGContextMoveToPoint(context, 10.0f, 10.0f); CGContextAddLineToPoint(context, 20.0f, 20.0f); CGContextStrokePath(context);

The first call specifies that lines used to create the current path should be drawn 4 pixels wide. Think of this as selecting the size of the brush you’re about to paint with. Until you call this function again with a different number, all lines will have a width of four lines when drawn. We then specify that the stroke color should be red. In Core Graphics, two colors are associated with drawing actions:

The stroke color is used in drawing lines and for the outline of shapes.

The fill color is used to fill in shapes.

A context has a sort of invisible pen associated with it that does the line drawing. As drawing commands are executed, the movements of this pen form a path. When you call CGContextMoveToPoint(), you move the end point of the current path to that location, without actually drawing anything. Whatever operation comes next, it will do its work relative to the point to which you moved the pen. In the earlier example, for instance, we first moved the pen to (10, 10). The next function call drew a line from the current pen location (10, 10) to the specified location (20, 20), which became the new pen location.

When you draw in Core Graphics, you’re not drawing anything you can actually see. You’re creating a path, which can be a shape, a line, or some other object, but it contains no color or other features to make it visible. It’s like writing in invisible ink. Until you do something to make it visible, your path can’t be seen. So, the next step is to tell

www.it-ebooks.info

566

CHAPTER 16: Drawing with Quartz and OpenGL

Quartz to draw the line using CGContextStrokePath(). This function will use the line width and the stroke color we set earlier to actually color (or “paint”) the path and make it visible.

The Coordinate System

In the previous chunk of code, we passed a pair of floating-point numbers as parameters to CGContextMoveToPoint() and CGContextLineToPoint(). These numbers represent positions in the Core Graphics coordinate system. Locations in this coordinate system are denoted by their x and y coordinates, which we usually represent as (x, y). The upper-left corner of the context is (0, 0). As you move down, y increases. As you move to the right, x increases.

In the previous code snippet, we drew a diagonal line from (10, 10) to (20, 20), which would look like the one shown in Figure 16–1.

Figure 16–1. Drawing a line using Quartz 2D’s coordinate system

The coordinate system is one of the gotchas in drawing with Quartz, because Quartz’s coordinate system is flipped from what many graphics libraries use and from the traditional Cartesian coordinate system (introduced by René Descartes in the seventeenth century). In OpenGL ES, for example, (0, 0) is in the lower-left corner, and as the y coordinate increases, you move toward the top of the context or view, as shown in Figure 16–2. When working with OpenGL, you must translate the position from the view’s coordinate system to OpenGL’s coordinate system. That’s easy enough to do, as you’ll see when we work with OpenGL ES later in the chapter.

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]