0% found this document useful (0 votes)
29 views74 pages

CG Chapter 3

Chapter 3 of the Computer Graphics course discusses graphics primitives, which are the basic building blocks for creating images. It covers geometric primitives, fill area primitives, and character primitives, as well as algorithms for drawing points and lines, including the DDA and Bresenham's algorithms. The chapter also explains how to implement these concepts in OpenGL for drawing lines and circles.

Uploaded by

awekedessie250
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views74 pages

CG Chapter 3

Chapter 3 of the Computer Graphics course discusses graphics primitives, which are the basic building blocks for creating images. It covers geometric primitives, fill area primitives, and character primitives, as well as algorithms for drawing points and lines, including the DDA and Bresenham's algorithms. The chapter also explains how to implement these concepts in OpenGL for drawing lines and circles.

Uploaded by

awekedessie250
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 74

Debre Markos University

Faculty of Technology
Department of Computer Science
CoSc 3072 – Computer Graphics
Chapter 3 – Graphics Primitives
 All graphics packages construct pictures from basic
building blocks known as graphics primitives.
 Geometric Primitives: Primitives that describe the
geometry, or shape, of these building blocks are
known as geometric primitives.
 They can be anything from 2- D primitives such as
points, lines and polygons to more complex 3-D
primitives such as spheres and polyhedra (a
polyhedron is a 3-D surface made from a mesh of 2-D
polygons).
 Fill Area Primitives: Refers to any enclosed boundary
that can be filled with a solid color or pattern.
02/22/2025
 Character Primitives: Used to display text characters
con…
In the following sections we will examine some algorithms for
drawing different primitives
OpenGL Point Drawing Primitives
The most basic type of primitive is the point.
Many graphics packages, including OpenGL, provide
routines for displaying points.
To recap, we use the pair of functions glBegin … glEnd,
using the symbolic constant GL_POINTS to specify how the
vertices in between should be interpreted.
 In addition, the function glPointSize can be used to set the
size of the points in pixels.
The default point size is 1 pixel. Points that have a size
greater than one pixel are drawn as squares with a side
length equal to their size.
02/22/2025
con…
For example, the following code draws three 2-D points with
a size of 2 pixels.
glPointSize(2.0);
glBegin(GL_POINTS);
glVertex2f(100.0, 200.0);
glVertex2f(150.0, 200.0);
glVertex2f(150.0, 250.0);
glEnd();

02/22/2025
Line Drawing Algorithms
Lines are a very common primitive and will be supported
by almost all graphics packages. In addition, lines form
the basis of more complex primitives such as polylines (a
connected sequence of straight-line segments) or
polygons (2-D objects formed by straight-line edges).
Lines are normally represented by the two end-points of
the line, and points (x,y) along the line must satisfy the
following slope-intercept equation:
* y = mx + c (1)

02/22/2025
Con….
*where m is the slope or gradient of the line, and c is
the coordinate at which the line intercepts the y-axis.
* Given two end-points (x0,y0) and (xend,yend), we
can calculate values for m and c as follows:

02/22/2025
DDA Line-Drawing Algorithm

The Digital Differential Analyser (DDA) algorithm


operates by starting at one end-point of the line, and
then using Eqs. (4) and (5) to generate successive
pixels until the second end-point is reached.
Therefore, first, we need to assign values for δx and
δy.
Before we consider the actual DDA algorithm, let us
consider a simple first approach to this problem.
Suppose we simply increment the value of x at
each iteration (i.e. δx = 1), and then compute the
corresponding value for y using Eqs. (2) and (4).

02/22/2025
Con...
This would compute correct line points
but, as illustrated by Figure 1, it would
leave gaps in the line.
The reason for this is that the value of δy
is greater than one, so the gap between
subsequent points in the line is greater
than 1 pixel.

Figure 1 – ‘Holes’ in a Line Drawn


by Incrementing x and Computing
the Corresponding y-Coordinate
02/22/2025
Con….
The solution to this problem is to make sure
that both δx and δy have values less than or
equal to one.
To ensure this, we must first check the size of
the line gradient. The conditions are:
*If |m| ≤ 1:
δx = 1
δy = m
*If |m| > 1:
δx = 1/m
δy = 1

02/22/2025
Con….
Once we have computed values for δx and δy,
the basic DDA algorithm is:
*Start with (x ,y )
0 0

Find successive pixel positions by adding on


(δx, δy) and rounding to the nearest integer, i.e.
* xk+1 = xk + δx
* yk+1 = yk + δy
For each position (xk,yk) computed, plot a line
point at (round(xk),round(yk)), where the round
function will round to the nearest integer.
Note that the actual pixel value used will be
calculated by rounding to the nearest integer,
but we keep the real-valued location for
calculating the next pixel position.
02/22/2025
Con…
*Let us consider an example of applying the DDA
algorithm for drawing a straight-line segment. Referring
to see Figure 2, we first compute a value for the gradient
m:

Now, because |m| ≤ 1, we compute δx and δy as follows:

δx = 1
δy = 0.6
Using these values of δx and δy we can now start to plot line
points:

02/22/2025
Con….
*Start with (x ,y ) = (10,10) – colour this pixel
0 0

*Next, (x ,y ) = (10+1,10+0.6) = (11,10.6) – so we


1 1

colour pixel (11,11)


*Next, (x ,y ) = (11+1,10.6+0.6) = (12,11.2) – so we
2 2

colour pixel (12,11)


*Next, (x ,y ) = (12+1,11.2+0.6) = (13,11.8) – so we
3 3

colour pixel (13,12)


*Next, (x ,y ) = (13+1,11.8+0.6) = (14,12.4) – so we
4 4

colour pixel (14,12)


*Next, (x ,y ) = (14+1,12.4+0.6) = (15,13) – so we
5 5

colour pixel (15,13)


*We have now reached the end-point (x end ,yend), so the
algorithm terminates
02/22/2025
Con….

Figure 2 - The Operation of the DDA Line-Drawing


Algorithm

02/22/2025
Con..
The DDA algorithm is simple and easy to implement,
but it does involve floating point operations to calculate
each new point.
 Floating point operations are time-consuming when
compared to integer operations.
Since line-drawing is a very common operation in
computer graphics, it would be nice if we could devise a
faster algorithm which uses integer operations only.
The next section describes such an algorithm.

02/22/2025
Bresenham’s Line-Drawing Algorithm
Bresenham’s line-drawing algorithm provides significant
improvements in efficiency over the DDA algorithm.
These improvements arise from the observation that for
any given line, if we know the previous pixel location, we
only have a choice of 2 locations for the next pixel.
This concept is illustrated in Figure 3: given that we know
(xk,yk) is a point on the line, we know the next line point
must be either pixel A or pixel B.
Therefore we do not need to compute the actual floating-
point location of the ‘true’ line point; we need only make a
decision between pixels A and B.
.

02/22/2025
Con…

Figure 3 - Bresenham's Line-Drawing Algorithm


 Bresenham’s algorithm works as follows.
 First, we denote by dupper and dlower the distances between the centres
of pixels A and B and the ‘true’ line (see Figure 3).
 Using Eq. (1) the ‘true’ y-coordinate at xk+1 can be calculated as:

02/22/2025
Con…..

Now, we can decide which of pixels A and B to choose based on


comparing the values of dupper and dlower:
If dlower > dupper, choose pixel A
Otherwise choose pixel B
We make this decision by first subtracting dupper from dlower:

02/22/2025
Con…..
*Now, we can decide which of pixels A and B to choose
based on comparing the values of dupper and dlower:
*If dlower > dupper, choose pixel A
*Otherwise choose pixel B
*We make this decision by first subtracting dupper from
dlower:
Decision variable pk=dlower-dupper

02/22/2025
Con….

 If the value of this expression is positive we choose pixel A; otherwise we


choose pixel B.
 The question now is how we can compute this value efficiently.
 To do this, we define a decision variable pk for the kth step in the
algorithm and try to formulate pk so that it can be computed using only
integer operations.
 To achieve this, we substitute m = Dy / Dx(where Δx and Δy are the
horizontal and vertical separations of the two line end-points) and define
pk as:

02/22/2025
Con….
where d is a constant that has the value
2Dy + 2cDx - Dx .
Note that the sign of pk will be the same as
the sign of (dlower – dupper), so if pk is
positive we choose pixel A and if it is negative
we choose pixel B.
In addition, pk can be computed using only
integer calculations, making the algorithm
very fast compared to the DDA algorithm.

02/22/2025
Con….
An efficient incremental calculation makes Bresenham’s algorithm
even faster.
(An incremental calculation means we calculate the next value of
pk from the last one.)
 Given that we know a value for pk, we can calculate pk+1 from
Eq. (10) by observing that:

Therefore we can define the incremental calculation as:


Pk=2Dyxk - 2Dxyk
P k n e x t = 2Dyxknext - 2Dxyknext = xknext=xk+1

02/22/2025
Con….

Therefore we can define the incremental calculation as:

02/22/2025
Con….

So we can see that we never need to compute the value of


the constant d in Eq. (10).

02/22/2025
Con…..
*Exercise
*Consider the example of plotting the line shown in
Figure 2 using Bresenham’s algorithm:

02/22/2025
Con…

02/22/2025
Con….

*We can see that the algorithm plots exactly


the same points as the DDA algorithm but it
computes them using only integer operations.
*Forthis reason, Bresenham’s algorithm is the
most popular choice for line-drawing in
computer graphics.

02/22/2025
OpenGL Line Functions
We can draw straight-lines in OpenGL using the
same glBegin … glEnd functions that we saw for
point-drawing.
This time we specify that vertices should be
interpreted as line end-points by using the symbolic
constant GL_LINES. For example, the following code:
*glLineWidth(3.0);
*glBegin(GL_LINES);
*glVertex2f(100.0, 200.0);
*glVertex2f(150.0, 200.0);
*glVertex2f(150.0, 250.0);
*glVertex2f(200.0, 250.0);
*glEnd()
02/22/2025
Con…..
will draw two separate line segments: one from (100,200)
to (150,200) and one from (150,250) to (200,250).
The line will be drawn in the current drawing colour and
with a width defined by the argument of the function
glLineWidth.
Two other symbolic constants allow us to draw slightly
different types of straight-line primitive: GL_LINE_STRIP
and GL_LINE_LOOP.
The following example illustrates the difference between
the three types of line primitive.
 First we define 5 points as arrays of 2
Glint values. Next,
we define exactly the same vertices for each of the three
types of line primitive.
The images to the right show how the vertices will be
interpreted by each primitive.
02/22/2025
Con…
*Glint p1[] = {200,100}; Glint p2[] = {50,0}
*Glint p3[] = {100,200}; Glint p4[] = {150,0}; Glint p5[]
= {0,100};
*glBegin(GL_LINES);
*glVertex2iv(p1);
*glVertex2iv(p2);
*glVertex2iv(p3);
*glVertex2iv(p4);
*glVertex2iv(p5);
*glEnd();

02/22/2025
Con….
*lBegin(GL_LINE_STRIP);
*glVertex2iv(p1);
*glVertex2iv(p2);
*glVertex2iv(p3);
*glVertex2iv(p4);
*glVertex2iv(p5);
*glEnd();
*glBegin(GL_LINE_LOOP);
*glVertex2iv(p1);
*glVertex2iv(p2);
*glVertex2iv(p3);
*glVertex2iv(p4);
*glVertex2iv(p5);
*glEnd(); 02/22/2025
Con…..
We can see that GL_LINES treats the vertices as
pairs of end-points.
Lines are drawn separately and any extra vertices
(i.e. a start-point with no end-point) are ignored.
GL_LINE_STRIP will create a connected polyline, in
which each vertex is joined to the one before it and
after it.
The first and last vertices are only joined to one
other vertex.
Finally, GL_LINE_LOOP is the same as GL_LINE_STRIP
except that the last point is joined to the first one to
create a loop.

02/22/2025
Circle-Drawing Algorithms
*Some graphics packages allow us to draw circle
primitives. Before we examine algorithms for circle-
drawing we will consider the mathematical equations of
a circle. In Cartesian coordinates we can write:

02/22/2025
Plotting Points Using Cartesian Coordinates

 As a first attempt at a circle-drawing


algorithm we can use the Cartesian
coordinate representation.
 Suppose we successively increment the x-
coordinate and calculate the corresponding
y-coordinate using Eq. (14):

02/22/2025
Con…
This would correctly generate points on the boundary of
a circle.
However, like the first attempt at a line-drawing
algorithm we saw in Section 3.1 (see Figure 1) we would
end up with ‘holes’ in the line – see Figure 4.
We would have the same problem if we incremented
the y-coordinate and plotted a calculated x-coordinate.
As with the DDA line-drawing algorithm we can
overcome this problem by calculating and checking the
gradient: if |m| ≤ 1 then increment x and calculate y,
and if |m| > 1 then increment y and calculate x.

02/22/2025
Con….

However, with the DDA algorithm we only needed to


compute and check the gradient once for the entire line,
but for circles the gradient changes with each point
plotted, so we would need to compute and check the
gradient at each iteration of the algorithm.
This fact, in addition to the square root calculation in Eq.
(17), would make the algorithm quite inefficient

Figure 4 - Circle-Drawing by Plotting Cartesian


Coordinates

02/22/2025
Plotting Points Using Polar Coordinates
*An alternative technique is to use the polar coordinate
equations.
*Recall that in polar coordinates we express a position
in the coordinate system as an angle θ and a distance
r.
* For a circle, the radius r will be constant, but we can
increment θ and compute the corresponding x and y
values according to Eqs. (15) and (16).
*For example, suppose we want to draw a circle with
(xc,yc) = (5,5) and r = 10. We start with θ = 0o and
compute x and y as:
*x = 5 + 10 cos 0o = 15
*y = 5 + 10 sin 0o = 5
*Therefore we plot (15,5) Next, we increase θ to 5o:
*x = 5 + 10 cos 5o = 14.96
*y = 5 + 10 sin 5o = 5.87 02/22/2025
*Therefore we plot (15,6)
Con……
This process would continue until we had plotted the
entire circle (i.e. θ = 360o).
Using this polar coordinate technique, we can avoid holes
in the boundary if we make small enough increases in the
value of θ.
This algorithm is more efficient than the Cartesian
plotting algorithm described in Section 4.1.
It can be made even more efficient, at a slight cost in
quality; by increasing the size of the steps in the value of
θ and then joining the computed points by straight- line
segments (see Figure 5).

02/22/2025
Con….

Figure 5 - Circle-Drawing by Plotting Polar Coordinates

02/22/2025
Taking Advantage of the Symmetry of Circles in
Plotting
We can improve the efficiency of any circle-drawing
algorithm by taking advantage of the symmetry of
circles.
 As illustrated in Figure 6, when we compute the
Cartesian coordinates x and y of points on a circle
boundary we have 4 axes of symmetry (shown in blue):
we can generate a point reflected in the y-axis by
negating the x-coordinate; we can generate a point
reflected in the x-axis by negating the y-coordinate, and
so on.
 In total, for each point computed, we can generate
seven more through symmetry.
Computing these extra points just by switching or
negating the coordinates of a single point is much more
efficient than computing each boundary point
separately.
This 02/22/2025
means that we only need to compute boundary
Con……

Figure 6 - Four-Way Symmetry of Circles

02/22/2025
Midpoint Circle-Drawing Algorithm

The midpoint algorithm takes advantage of the


symmetry property of circles to produce a more efficient
algorithm for drawing circles.
The algorithm works in a similar way to Bresenham’s
line-drawing algorithm, in that it formulates a decision
variable that can be computed using integer operations
only.
The midpoint algorithm is illustrated in Figure 7. Recall
that we only need to draw one octant of the circle, as
the other seven octants can be generated by symmetry.

02/22/2025
Con….

Figure 7 - The Midpoint Circle-Drawing


Algorithm

02/22/2025
Con…..

02/22/2025
Con……

02/22/2025
Con……
* pk =fcirc(xk+1, yk- 0.5) = (xk+1)2 + (yk- 0.5)2 - r2
* Pk=xk2+2xk+1+yk2-yk+1/4-r2 know we can calculate pknext=pk+1
*Pk next= xknext2+2xknext+1+yknext2-yknext+1/4-r2

* The consecutive pk value will be:


* Pk -pk=pk+1-pk
next

* If pk<0
* pk+1-pk=(X +1)2+2x k k+1 +1+yk2-yk+1/4- 2- ((Xk+1) 2+yk2-yk+1/4-r2 )=
r
*pk+1-pk=2xk+1+1=>pk+1=pk+ 2x +1 k+1

*If pk>0
*yk+1=yk-1
*Pk+1-pk=(Xk+1)2+2x +1+(yk-1)2-(yk-1)+1/4-r2- ((Xk+1) 2+yk2-yk+1/4-r2 )
k+1

*= (X +1)2+2x +1+y 2-2y +1-yk+1+1/4-r2-((X +1) 2+y 2-yk+1/4-r2 )


k k+1 k k k k

*Pk+1-pk=2x +1-2y +1=2x +1-2y +2=>2x +1-2(y


k+1 k k+1 k k+1 k-1)

*Pk+1=pk+2x k+1+1 -2yk+1

* p0 =fcirc(1, r - 0.5) = 1 + (r - 0.5)2 - r2 = 5 - r to find the value of p0 substitute (0,r) in the circle midpoint
formula 02/22/2025
Con…..

02/22/2025
Con…..

02/22/2025
*Fill-Area

Primitives
The most common type of primitive in 3-D computer
graphics is the fill-area primitive.
 The term fill-area primitive refers to any enclosed
boundary that can be filled with a solid color or pattern.
 However, fill-area primitives are normally polygons, as
they can be filled more efficiently by graphics packages.
Polygons are 2-D shapes whose boundary is formed by any
number of connected straight-line segments.
They can be defined by three or more coplanar vertices
(coplanar points are positioned on the same plane).
Each pair of adjacent vertices is connected in sequence by
edges.
Normally polygons should have no edge crossings: in this
case they are known as simple polygons or standard
polygons (see Figure 8).
02/22/2025
Con…..

Figure 8 - A Polygon with an Edge Crossing


Polygons are the most common form of graphics primitive because
they form the basis of polygonal meshes, which is the most common
representation for 3-D graphics objects.

Figure 9 - Examples of Polygonal Mesh Surfaces

02/22/2025
Convex and Concave Polygons

*We can differentiate between convex and concave


polygons:
*Convex polygons have all interior angles ≤ 180o
*Concave polygons have at least one interior angle > 180o
*The difference between convex and concave polygons is
shown in Figure 10.
* Many graphics packages (including OpenGL) require all
fill-area polygons to be convex polygons.
*The reason for this, as we will see in Chapter 3, is that it is
much more efficient to fill a polygon if we know it is
convex.

a) b)
Figure 10 – Types of Polygon: (a) Convex; (b)
Concave
02/22/2025
Polygon Inside-Outside Tests

*In order to fill polygons we need some way of telling if a


given point is inside or outside the polygon boundary: we
call this an inside-outside test.
* We will examine two different inside-outside tests: the
odd-even rule and the nonzero winding number rule.
*Both techniques give good results, and in fact usually their
results are the same, apart from for some more complex
polygons.
* Odd-Even Rule
*Using odd-even rule we can deteremine if point P is
inside or outside the polygon boundary by the
following steps:

02/22/2025
Con…

* Draw a line from P to some distant point (that is known to


be outside the polygon boundary).
* Count the number of crossings of this line with the
polygon boundary:
* If the number of crossings is odd, then P is inside the polygon
boundary.
* If the number of crossings is even, then P is outside the
polygon boundary.
* We can see from Figure 11(a) that the two white regions are
considered to be outside the polygon since they have two
line crossings to any distant points.

02/22/2025
Nonzero Winding Number Rule

*The nonzero winding number rule is similar to the


odd-even rule, and is illustrated in Figure 11(b).
*This time we consider each edge of the polygon to be
a vector, i.e. they have a direction as well as a
position.
*These vectors are directed in a particular order
around the boundary of the polygon (the programmer
defines which direction the vectors go).
*Now we decide if a point P is inside or outside the
boundary as follows:
* Draw a line from P to some distant point (that is known to be outside the
polygon boundary).
* At each edge crossing, add 1 to the winding number if the edge goes
from right to left, and subtract 1 if it goes from left to right.
* If the total winding number is nonzero, P is inside the polygon boundary.
* If the total winding number is zero, P is outside the polygon boundary.
02/22/2025
Con….

*we can see from Figure 11(b) that the nonzero winding
number rule gives a slightly different result from the odd-
even rule for the example polygon given.
*In fact, for most polygons (including all convex polygons)
the two algorithms give the same result.
*But for more complex polygons such as that shown in
Figure 11 the nonzero winding number rule allows the
programmer a bit more flexibility, since they can control
the order of the edge vectors to get the results they want.

Figure 11 - Inside-Outside Tests for


Polygons 02/22/2025
Representing Polygons

*Polygons, and in particular convex polygons, are the most


common type of primitive in 3-D graphics because they
are used to represent polygonal meshes
*But how can polygonal meshes be represented? A
common technique is to use
*tables of data. These tables can be of two different types:
*Geometric tables: These store information about the
geometry of the polygonal mesh, i.e. what are the
shapes/positions of the polygons?
*Attribute tables: These store information about the
appearance of the polygonal mesh, i.e. what colour is it, is
it opaque or transparent, etc.
* This information can be specified for each polygon
individually or for the mesh as a whole.

02/22/2025
Con….
Figure below shows a simple example of a geometric
table. We can see that there are three tables: a vertex
table, an edge table and a surface-facet table.
The edge table has pointers into the vertex table to
indicate which vertices comprise the edge.
Similarly the surface-facet table has pointers into the
edge table.
This is a compact representation for a polygonal mesh,
because each vertex’s coordinates are only stored once, in
the vertex table, and also information about each edge is
only stored once.
*

02/22/2025
OpenGL Fill-Area Routines
OpenGL provides a variety of routines to draw fill-area
polygons. In all cases these polygons must be convex.
 In most cases the vertices should be specified in an anti-
clockwise direction when viewing the polygon from outside
the object, i.e. if you want the front-face to point towards
you.
The default fill-style is solid, in a color determined by the
current color settings.
In all, there are seven different ways to draw polygons in
OpenGL:
*glRect*
Six different symbolic constants for use with glBegin …
glEnd
We will now consider each of these techniques in turn.
*glRect*
02/22/2025
Con….
Two-dimensional rectangles can also be drawn using some
of the other techniques described below, but because
drawing rectangles in 2-D is a common task OpenGL
provides the glRect* routine especially for this purpose
(glRect* is more efficient for 2-D graphics than the other
alternatives).
The basic format of the routine is:
*glRect* (x1, y1, x2, y2)
*where (x1,y1) and (x2,y2) define opposite corners of the
rectangle. Actually when we call the glRect* routine,
OpenGL will construct a polygon with vertices defined in
the following order:
*(x1,y1), (x2,y1), (x2,y2), (x1,y2)
*For example, Figure 12 shows an example of executing the
following call to glRecti:
*glRecti(200,100,50,250); 02/22/2025
Con….

Figure 12 - Drawing a 2-D Rectangle with the OpenGL


routine glRect*

02/22/2025
Con….
* GL_POLYGON
*The GL_POLYGON symbolic constant defines a single convex
polygon. Like all of the following techniques for drawing fill-
area primitives it should be used as the argument to the
glBegin routine. For example, the code shown below will draw
the shape shown in Figure 13. Notice that the vertices of the
*polygon are specified in anti-clockwise order.
* glBegin(GL_POLYGON);
* glVertex2iv(p1);
* glVertex2iv(p2);
* glVertex2iv(p3);
* glVertex2iv(p4);
* glVertex2iv(p5); Figure 13 - A Polygon Drawn Using
the GL_POLYGON OpenGL Primitive
* glVertex2iv(p6);
* glEnd();
02/22/2025
Con…..
*GL_TRIANGLES
*The GL_TRIANGLES symbolic constant causes the glBegin …
glEnd pair to treat the vertex list as groups of three 3
vertices, each of which defines a triangle.
* The vertices of each triangle must be specified in anti-
clockwise order. Figure 14 illustrates the use of the
GL_TRIANGLES primitive.
*glBegin(GL_TRIANGLES);
*glVertex2iv(p1);
* glVertex2iv(p2);
* glVertex2iv(p6);
* glVertex2iv(p3);
*glVertex2iv(p4);
*glVertex2iv(p5);
*glEnd(); 02/22/2025
Con..
GL_TRIANGLE_STRIP
*To form polygonal meshes it is often convenient to define a
number of triangles using a single glBegin … glEnd pair. The
GL_TRIANGLE_STRIP primitive enables us to define a strip of
connected triangles. The vertices of the first triangle only must
be specified in anti-clockwise order. Figure 15 illustrates the
use
*of GL_TRIANGLE_STRIP.
*glBegin(GL_TRIANGLE_STRIP);
*glVertex2iv(p1);
*glVertex2iv(p2);
*glVertex2iv(p6);
* glVertex2iv(p3);
*glVertex2iv(p5);
*glVertex2iv(p4);
*glEnd(); 02/22/2025
Con…
* GL_TRIANGLE_FAN
 GL_TRIANGLE_FAN is similar to
GL_TRIANGLE_STRIP, in that it allows us to define
a number of triangles using a single glBegin …
glEnd command.
 In this case, we can define a ‘fan’ of triangles
emanating from a single point.
The first point of the first triangle is the source of
the fan, and the vertices of this triangle must be
specified in an anti-clockwise direction.
In addition, the fan of triangles must also be
defined in an anti-clockwise direction. See Figure
below for an example of the use of
GL_TRIANGLE_FAN.
02/22/2025
Con…
* glBegin(GL_TRIANGLE_FAN);
* glVertex2iv(p1);
* glVertex2iv(p2);
* glVertex2iv(p3);
* glVertex2iv(p4);
* glVertex2iv(p5);
* glVertex2iv(p6);
* glEnd();
GL_QUADS
* Using the GL_QUADS primitive, the vertex list is treated as
groups of four vertices, each of which forms a quadrilateral.
* If the number of vertices specified is not a multiple of four,
then the extra vertices are ignored.
* The vertices for each quadrilateral must be defined in an anti-
clockwise direction.
02/22/2025
Con…
*glBegin(GL_QUADS);
*glVertex2iv(p1);
*glVertex2iv(p2);
*glVertex2iv(p3);
*glVertex2iv(p4);
* glVertex2iv(p5);
*glVertex2iv(p6);
*glVertex2iv(p7);
* glVertex2iv(p8);
*glEnd();

02/22/2025
Con…
*GL_QUAD_STRIP
*In the same way that GL_TRIANGLE_STRIP allowed us to
define a strip of connected triangles, GL_QUAD_STRIP
allows us to define a strip of quadrilaterals. The first four
vertices form the first quadrilateral, and each subsequent
pair of vertices is combined with the two before them to
form another quadrilateral. The vertices of the first
quadrilateral must be specified in an anti-clockwise
direction. Figure 18 illustrates the use of GL_QUAD_STRIP.

02/22/2025
Con…
*glBegin(GL_QUAD_STRIP);
*glVertex2iv(p1);
*glVertex2iv(p2);
*glVertex2iv(p3);
*glVertex2iv(p4);
*glVertex2iv(p5);
*glVertex2iv(p6);
*glVertex2iv(p7);
*glVertex2iv(p8);
*glEnd();

02/22/2025
Character Primitives
The final type of graphics primitive we will consider is the
character primitive.
Character primitives can be used to display text characters.
Before we examine how to display characters in OpenGL, let us
consider some basic concepts about text characters.
We can identify two different types of representation for
characters: bitmap and stroke (or outline) representations.
Using a bitmap representation (or font), characters are stored
as a grid of pixel values (see Figure 19(a)).
This is a simple representation that allows fast rendering of the
character.
However, such representations are not easily scalable: if we
want to draw a larger version of a character defined using a
bitmap we will get an aliasing effect (the edges of the
characters will appear jagged due to the low resolution).
 Similarly, we cannot easily generate bold or italic versions of
the character.
02/22/2025
Con…
An alternative representation to bitmaps is the stroke, or
outline, representation (see Figure 19(b)).
Using stroke representations characters are stored using
line or curve primitives.
To draw the character we must convert these primitives
into pixel values on the display.
As such, they are much more easily scalable: to generate
a larger version of the character we just multiply the
coordinates of the line/curve primitives by some scaling
factor.
Bold and italic characters can be generated using a
similar approach.
The disadvantage of stroke fonts is that they take longer
time to draw than bitmap fonts.

02/22/2025
Character Primitives
*Finally, we can categorise fonts as either monospace or
proportional fonts.
*Characters drawn using a monospace font will always take
up the same width on the display, regardless of which
character is being drawn.
*With proportional fonts, the width used on the display will
be proportional to the actual width of the character, e.g.
the letter ‘i’ will take up less width than the letter ‘w’.
*As shown below, Courier is an example of a monospace
font whereas Times-Roman and Arial are examples of
proportional fonts:
*Courier is a monospace font
*Times-Roman is a proportional font

02/22/2025
Character Primitives

Bitmap and Stroke Character


Primitives

02/22/2025
* OpenGL Character Primitive
*OpenGL on its own does not contain any routines
Routines
dedicated to drawing text characters.
* However, the glut library does contain two different
routines for drawing individual characters (not strings).
*Before drawing any character, we must first set the raster
position, i.e. where will the character be drawn. We need
to do this only once for each sequence of characters.
*After each character is drawn the raster position will be
automatically updated ready for drawing the next
character.
* To set the raster position we use the glRasterPos2i
routine. For example,
* glRasterPos2i(x, y)
* positions the raster at coordinate location (x,y).
02/22/2025
Con….
*Next, we can display our characters.
*The routine we use to do this will depend on whether we
want to draw a bitmap or stroke character. For bitmap
characters we can write, for example,
*glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ‘a’);
*This will draw the character ‘a’ in a monospace bitmap
font with width 9 and height 15 pixels.
*There are a number of alternative symbolic constants that
we can use in place of GLUT_BITMAP_9_BY_15 to specify
different types of bitmap font. For example,
*GLUT_BITMAP_8_BY_13
*GLUT_BITMAP_9_BY_15

02/22/2025
Con….
*We can specify proportional bitmap fonts using the
following symbolic constants:
*GLUT_BITMAP_TIMES_ROMAN_10
*GLUT_BITMAP_HELVETICA_10
*Here, the number represents the height of the font.
* Alternatively, we can use stroke fonts using the
glutStrokeCharacter routine.
* For example,glutStrokeCharacter(GLUT_STROKE_ROMAN,
‘a’);
*This will draw the letter ‘a’ using the Roman stroke font,
which is a proportional font.
*We can specify a monospace stroke font using the
following symbolic constant:
*GLUT_STROKE_MONO_ROMAN
02/22/2025
Con….

Thank You!!!!!!!!!!

02/22/2025

You might also like