Computer Graphics Lab Manual For Promotion
Computer Graphics Lab Manual For Promotion
Jun,2012 E.C
Debre Markos, Ethiopia
Objectives of The Laboratory manual
The main objective of this laboratory manual is to provide a unified introduction to computer graphics using
Dev C++ and OpenGL API for students with an interest in imaging or digital visual arts and to the highest
extent, create animated objects and video game development. Drawing points, lines and images in OpenGL,
3D polygon rendering and transformations are discussed perceptively. Example codes, exercises and further
working practices will be given in C++ using the OpenGL API.
Contents
CHAPTER ONE........................................................................................................................................5
1. Definitions and Terminologies of Computer Graphics and Setting up Working Environments.5
1.1 Definition.....................................................................................................................................5
1.2 Setting up the Environment.........................................................................................................6
1.3 Launch our first code...................................................................................................................9
1.4 Naming Convention for OpenGL Functions..............................................................................11
CHAPTER TWO.....................................................................................................................................13
2. Graphics Primitives.........................................................................................................................13
2.1 Introduction.............................................................................................................................13
2.2 Drawing Points.........................................................................................................................13
2.3 Drawing Lines, Line Strip and Line Loop.............................................................................19
2.4 Drawing Triangle, Triangle strip and Triangle Fan.............................................................23
2.5 Drawing a Circle......................................................................................................................24
2.5.1 Bresenham’s Algorithm...................................................................................................25
2.6 Drawing Polygons.....................................................................................................................28
2.6.1 Polygon filling Algorithms...............................................................................................30
2.7 Other Callback Functions.......................................................................................................35
Learning Outcomes of The Laboratory manual
By the end of the laboratory manual the student will be able to:
Rendering is the process of generating an image from a model (or models in what collectively could be
called a scene file), by means of computer programs.
OpenGL provides a consistent interface to the underlying graphics hardware. This abstraction allows a
single program to run a different graphics hardware easily. A program written with OpenGL can even be run
in software (slowly)on machines with no graphics acceleration. OpenGL function names always begin
with gl, such as glClear(), and they may end with characters that indicate the types of the parameters, for
example glColor3f(GLfloat red, GLfloat green, GLfloat blue) takes three floating-point color parameters and
glColor4dv(const GLdouble *v) takes a pointer to an array that contains 4 double-precision floating-point
values. OpenGL constants begin with GL, such as GL DEPTH. OpenGL also uses special names for types
that are passed to its functions, such as GLfloat or GLint, the corresponding C types are compatible, that is
float and int respectively.
GLU is the OpenGL utility library. It contains useful function sat a higher level than those provided by
OpenGL, for example, to draw complex shapes or set up cameras. All GLU functions are written on top of
OpenGL. Like OpenGL, GLU function names begin with glu, and constants begin with GLU.
GLUT, the OpenGL Utility Toolkit, provides a system for setting up callbacks for interacting with the user
and functions for dealing with the windowing system. This abstraction allows a program to run on different
operating systems with only a recompile. Glut follows the convention of prepending function names with
glut and constants with GLUT.
First, download Dev C++ and freeglut from the site. Install Dev C++ and extract zipped freeglut file.
Installing Dev C++ creates a folder C:\Program Files (x86)\Dev-Cpp
Now open the folder until you got to the folder shown below and we have to copy files in freeglut folder to
the correct folder shown below.
Now as you see there are folders in the Dev-Cpp and the freeglut folders with the same name. what we have
to do is copy files inside the freeglut and past it to the folders found in Dev-Cpp folder and here is the
address to show which one to past where. Copy files found inside the following address and past to the
located one.
1. E:\Setup\freeglut-MinGW-3.0.0-1.mp\freeglut\include\GL ==== C:\Program Files (x86)\Dev-Cpp\
MinGW64\x86_64-w64-mingw32\include\GL
2. E:\Setup\freeglut-MinGW-3.0.0-1.mp\freeglut\lib\x64 ===C:\Program Files (x86)\Dev-Cpp\
MinGW64\x86_64-w64-mingw32\lib
3. E:\Setup\freeglut-MinGW-3.0.0-1.mp\freeglut\bin\x64====C:\Windows\System32
N.B: - step 1 and 2 are copied directly from freeglut folders to Dev-Cpp folders and the 3rd step is copied
from freeglut folder to windows System32 folder. Remember to copy all files found in the folders to the
indicated folders.
Filenewproject and select basic from the menus console application and C++ project radio button. On
the name text box give a name for your project.
Then hit ok or Enter and you will get a working area with iostream.h header and main function, remove the
iostream.h header, no need to use it. Go to project project options parameters and in the linkers text
area and add the following:-
-lopengl32
-lfreeglut
-lglu32
Tip: - if you create a new project remember to add the above parameters each(creating a new project) time.
/* Handler for window-repaint event. Call back when the window first appears and
whenever the window needs to be re-painted. */
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer (background)
Output: -
OpenGL operates as a state machine, and maintain a set of state variables (such as the foreground color,
background color, and many more). In a state machine, once the value of a state variable is set, the value
persists until a new value is given.
For example, we set the "clearing" (background) color to black once in initGL(). We use this setting to clear
the window in the display() repeatedly (display() is called back whenever there is a window re-paint request)
- the clearing color is not changed in the entire program.
// In display(), clear the color buffer (i.e., set background) with the current "clearing" color
glClear(GL_COLOR_BUFFER_BIT);
Another example: If we use glColor function to set the current foreground color to "red", then "red" will be
used for all the subsequent vertices, until we use another glColor function to change the foreground color.
In a state machine, everything shall remain until you explicitly change it!
begins with lowercase gl (for core OpenGL), glu (for OpenGL Utility) or glut (for OpenGL Utility
Toolkit).
followed by the purpose of the function, in camel case (initial-capitalized), e.g., glColor to specify the
drawing color, glVertex to define the position of a vertex.
followed by specifications for the parameters, e.g., glColor3f takes three float parameters. glVectex2i
takes two int parameters.
(This is needed as C Language does not support function overloading. Different versions of the
function need to be written for different parameter lists.)
The function may take 2, 3, or 4 parameters, in type of s (GLshort), i (GLint), f (GLfloat) or d (GLdouble).
The 'v' (for vector) denotes that the parameters are kept in an array of 2, 3, or 4 elements, and pass into the
function as an array pointer.
Floating-point numbers: GLfloat (32-bit), GLdouble (64-bit), GLclampf and GLclampd (between 0.0
and 1.0).
GLboolean (unsigned char with 0 for false and non-0 for true).
OpenGL's constants begins with "GL_", "GLU_" or "GLUT_", in uppercase separated with underscores, e.g.,
GL_COLOR_BUFFER_BIT.
For examples,
CHAPTER TWO
2. Graphics Primitives
2.1 Introduction
All graphics packages construct pictures from basic building blocks known as graphics 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).
In the following sections we will examine some algorithms for drawing different primitives, and
where appropriate we will introduce the routines for displaying these primitives in OpenGL
Let’s see the basic primitive, point and define each function and method used in the process of drawing it.
/*
* pointPrimitive.cpp: Vertex, Primitive and Color
* Draw Simple 2D colored point.
*/
#include <windows.h> // for MS Windows
#include <GL/glut.h> // GLUT, include glu.h and gl.h
/* Initialize OpenGL Graphics */
void initGL() {
// Set "clearing" or background color
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black and opaque
}
/* Handler for window-repaint event. Call back when the window first appears and
whenever the window needs to be re-painted. */
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer with current clearing color
// Define shapes enclosed within a pair of glBegin and glEnd
glPointSize(4);//Set the size of a point
glBegin(GL_POINTS); // one vertex forms a point
glColor3f(1.0,0.0,0.0);
glVertex2f(.2,.2);
glEnd();
glFlush(); // Render now
}
/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("Vertex, Primitive & Color"); // Create window with the given title
glutInitWindowSize(320, 320); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutDisplayFunc(display); // Register callback handler for window re-paint event
initGL(); // Our own OpenGL initialization
glutMainLoop(); // Enter the event-processing loop
return 0;
}
#include <windows.h>
#include <GL/glut.h>
We also included the GLUT header, which is guaranteed to include "glu.h" (for GL Utility) and "gl.h" (for
Core OpenGL).
GLUT provides high-level utilities to simplify OpenGL programming, especially in interacting with the
Operating System (such as creating a window, handling key and mouse inputs). The following GLUT
functions were used in the above program:
glutInit: initializes GLUT, must be called before other GL/GLUT functions. It takes the same
arguments as the main().
glutDisplayFunc: registers the callback function (or event handler) for handling window-paint event.
The OpenGL graphic system calls back this handler when it receives a window re-paint request. In
the example, we register the function display() as the handler.
glutMainLoop: enters the infinite event-processing loop, i.e, put the OpenGL graphics system to
wait for events (such as re-paint), and trigger respective event handlers (such as display()).
void glutMainLoop()
The initGL() is meant for carrying out one-time OpenGL initialization tasks, such as setting the clearing
color. initGL() is invoked once (and only once) in main().
The function display() is known as a callback event handler. An event handler provides the response to a
particular event (such as key-press, mouse-click, window-paint). The function display() is meant to be the
handler for window-paint event. The OpenGL graphics system calls back display() in response to a window-
paint request to re-paint the window (e.g., window first appears, window is restored after minimized, and
window is resized). Callback means that the function is invoked by the system, instead of called by the your
program.
The Display() runs when the window first appears and once per subsequent re-paint request. Observe that we
included OpenGL graphics rendering code inside the display() function, so as to re-draw the entire window
when the window first appears and upon each re-paint request.
glutInitWindowSize(320, 320);
glutInitWindowPosition(50, 50);
We initialize the GLUT and create a window with a title, an initial size and position.
glutDisplayFunc(display);
We register display() function as the callback handler for window-paint event. That is, display() runs when
the window first appears and whenever there is a request to re-paint the window.
initGL();
We call the initGL() to perform all the one-time initialization operations. In this example, we set the clearing
(background) color once, and use it repeatably in the display() function.
glutMainLoop();
We then put the program into the event-handling loop, awaiting for events (such as window-paint request) to
trigger off the respective event handlers (such as display()).
We use glColor function to set the foreground color, and glClearColor function to set the background (or
clearing) color.
Notes:
In the above example, we set the background color via glClearColor in initGL(), with R=0, G=0, B=0 (black)
and A=1 (opaque and cannot see through).
In display(), we set the vertex color via glColor3f for subsequent vertices. For example, R=1, G=0, B=0
(red).
A geometric primitive is defined by specifying its vertices via glVertex function, enclosed within a pair
glBegin and glEnd.
void glEnd()
glBegin specifies the type of geometric object, such as GL_POINTS, GL_LINES, GL_QUADS,
GL_TRIANGLES, and GL_POLYGON. For types that end with 'S', you can define multiple objects of the
same type in each glBegin/glEnd pair. For example, for GL_TRIANGLES, each set of three glVertex's
defines a triangle.
The vertices are usually specified in float precision. It is because integer is not suitable for trigonometric
operations (needed to carry out transformations such as rotation). Precision of float is sufficient for carrying
out intermediate operations, and render the objects finally into pixels on screen (with resolution of says
800x600, integral precision). double precision is often not necessary.
glEnd();
We set the color to red (R=1, G=0, B=0). The vertex will have the color of red. Take note that in OpenGL,
color (and many properties) is applied to vertices rather than primitive shapes. The color of the a primitive
shape is interpolated (starts, emits) from its vertices.
glFlush();
This call flushes the graphics buffer, causing all data to be sent to the graphics window.
Suggested Exercises/Activities
Write down or copy the above project and try modifying some of the constant values used in the code to see
their effect. For example, change the window size and position, background and foreground colors, point size
and point positions. Also try adding some extra points to the image. How would you draw some points in a
different color to others?
glBegin(GL_LINES);
glVertex2i(100,150);
glVertex2i(140,150);
glVertex2i(120,130);
glVertex2i(120,170);
glEnd();
Note that the structure of the commands used to draw lines in OpenGL is the same as that we used to draw
points in previous code - the calls to glVertex2i are enclosed between the glBegin and glEnd statements. The
difference here is the argument to glBegin. When using the GL_LINES primitive the statements between
glBegin and glEnd should consist of pairs of calls to glVertex2i. Each pair specifies the starting and ending
point of the line to be drawn. For example, the code shown above draws two lines - one from (100,150) to
(140,150) and one from (120,130) to (120,170). No line is drawn from (140,150) to (120,130).
Sometimes we may want to draw several lines joined end to end. This is sometimes known as a polyline, and
can be achieved in OpenGL by using the GL_LINE_STRIP primitive.
glBegin(GL_LINE_STRIP);
glVertex2i(350,50);
glVertex2i(400,100);
glVertex2i(400,150);
glVertex2i(350,200);
glVertex2i(300,200);
glVertex2i(250,150);
glVertex2i(250,100);
glEnd();
This time each vertex is joined to the vertices before it and after it in the list.
when we draw line loop each vertex joined one after the other. But the main difference is the the last vertex
of the line joins the very beginning vertex of the first line and make it loop.
glBegin(GL_LINE_FAN);
glVertex2i(350,50);
glVertex2i(400,100);
glVertex2i(400,150);
glVertex2i(350,200);
glVertex2i(300,200);
glVertex2i(250,150);
glVertex2i(250,100);
glEnd();
Note: -
If you use the above code on the source code we use to draw a point, the vertices are out of the range of the plane, we
will discuss about the range of the plane later but for the time being what you have to do is add this code
void myInit(void) {
glClearColor(1.0, 1.0, 1.0, 0.0); // white background
gluOrtho2D(0.0, 640.0, 0.0, 480.0);
}
At the same time at main loop change windows size to: -
glutInitWindowSize(640,480);//you can increase the size but not less than the ortho2D
Basically, these statements are establishing a relationship between the coordinate system that we are
drawing in, and the coordinate system of the final graphics window.
OpenGL allows us to change both the line width and the line style. To change the line width we use the glLineWidth
routine. This takes a single floating point argument (which is rounded to the nearest integer) indicating the thickness of
the line in pixels. For example, glLineWidth(4.3) will set the line width state variable to 4 pixels. This value will be
used for all subsequent line primitives until the next call to glLineWidth. The ‘true’ line thickness will depend on the
orientation of the line. The line style is specified using a pixel mask. First we must enable the line stipple feature of
OpenGL using the following line: glEnable(GL_LINE_STIPPLE) Next, we use the glLineStipple function to define
the line style. glLineStipple takes two arguments: a repeat factor, which specifies how many times each bit in the pixel
mask should be repeated, and a pattern, which is a 16-bit pixel mask. For example, the code shown below draws the
dashed line shown to the right. The pixel mask is the hexadecimal number 00FF, which is 8 zeros followed by 8 ones.
The repeat factor is 1 so each one or zero in the pixel mask corresponds to a single pixel in the line.
glEnable(GL_LINE_STIPPLE);
glLineWidth(3.0);//You can increase the point size like line width by using glPointSize(size);, while size is the size of
the point.
glLineStipple(1, 0x00FF);
glBegin(GL_LINE_STRIP);
glVertex2i(100,100);
glVertex2i(150,100);
glVertex2i(150,200);
glVertex2i(250,250);
glEnd();
glDisable(GL_LINE_STIPPLE);
void display(void)
{
//Point attributes
glPointSize(10);
glBegin(GL_POINTS);
glColor4f(1.0,0,1.0,1.0);
glVertex2i(500,300);
glEnd( );
//Line attributes
glEnable(GL_LINE_STIPPLE);
glColor3f(0,1,0);
glBegin(GL_LINES);
glVertex2i(50,100);
glVertex2i(450,450);
glEnd( );
glEnable(GL_LINE_STIPPLE);
glLineWidth(3);
glColor3f(1,1,0);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(450,400);
glEnd( );
glColor3f(1,0,0);
glBegin(GL_LINES);
glVertex2i(100,50);
glVertex2i(500,400);
glEnd( );
glEnable(GL_LINE_STIPPLE);
Just like GL_LINES groups the specified vertices between glBegin and glEnd into pairs to form lines,
GL_TRIANGLES treats them as groups of three and uses them to draw triangles. Consider the following
lines.
glBegin(GL_TRIANGLES);
glColor3f(1.0,0.0,0.0);//sets the color of the vertex in anti-clockwise order
glVertex2f(0,0);
glColor3f(0.0,1.0,0.0);
glVertex2f(4,0);
glColor3f(1.0,1.0,0.0);
glVertex2f(2,3);
glEnd();
Triangle Strip is formed using two vertices from the first triangle when you add one vertex, then forms the second
triangle. This means if you have four vertices the first three forms one triangle and the fourth vertex connects with the
last two vertices and forms the second triangle. To do this we use GL_TRIANGLE_STRIP. Check the following
example.
glBegin(GL_TRIANGLE_STRIP);
glColor3f(1.0,1.0,0);
glVertex2i(0,25);
glVertex2i(25,150);
glVertex2i(150,25);
glVertex2i(25,25);//the fourth vertex.
glEnd( );
Note: -
In order to get clear output, you need to change your gluOrtho2D or plane surface depend on the vertices
you use.
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 anticlockwise direction. In addition, the fan of triangles must also be defined in an
anticlockwise direction. See Figure 23 for an example of the use of GL_TRIANGLE_FAN
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0,1.0,0);
glVertex2i(0,25);//all other vertices use this one as their 3rd vertex.
glVertex2i(25,150);
glVertex2i(150,25);
glVertex2i(25,150);
glVertex2i(150,150);
glVertex2i(25,25);
glEnd( );
Drawing a circle on the screen is a little complex than drawing a line. There are two popular algorithms for
generating a circle − Bresenham’s Algorithm and Midpoint Circle Algorithm. These algorithms are based on
the idea of determining the subsequent points required to draw the circle. Let us discuss the algorithms in
detail
We cannot display a continuous arc on the raster display. Instead, we have to choose the nearest pixel
position to complete the arc.
From the following illustration, you can see that we have put the pixel at (X, Y) location and now need to
decide where to put the next pixel − at N (X+1, Y) or at S (X+1, Y-1).
This can be decided by the decision parameter d.
Step 1 − Get the coordinates of the center of the circle and radius, and store them in x, y, and R
respectively. Set P=0 and Q=R.
#include<GL/glut.h>
#include<math.h>
#define PI 3.14
void myInit(void){
glClearColor(1.0,1.0,1.0,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,640.0,0.0,480.0);
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
GLint x=0,y,p,r=100,xc=150,yc=150;
y=r;
p=3-2*r;
glBegin(GL_POINTS);
glColor3f(1.0,0.0,0);
while(x<=y)
{
if(p<0)
p = p+(4*x+6);
else
{
glColor3f(1.0,0.0,0); y = y-1;
glColor3f(1.0,0.0,0);
p = p+4*(x-y)+10;
glColor3f(1.0,0.0,0);
}
glColor3f(1.0,0.0,0);
glVertex2i(xc+x, yc+y);
glColor3f(1.0,0.0,0);
glVertex2i(xc-x, yc+y);
glVertex2i(xc+x, yc-y);
glVertex2i(xc-x, yc-y);
glVertex2i(xc+y, yc+x);
glVertex2i(xc-y, yc+x);
glVertex2i(xc+y, yc-x);
glVertex2i(xc-y, yc-x);
x = x+1;
glColor3f(1.0,0.0,0);
}
glEnd( );
glFlush();
}
int main(int argc, char** argv){
glutInit(&argc,argv);
glutCreateWindow("Premetives");
glutInitWindowSize(640.0,480.0);
glutInitWindowPosition(10,10);
glutDisplayFunc(display);
myInit();
glutMainLoop();
glBegin(GL_POLYGON);
glVertex2i(350,250);
glVertex2i(400,300);
glVertex2i(400,350);
glVertex2i(350,400);
glVertex2i(300,400);
glVertex2i(250,350);
glVertex2i(250,300);
glVertex2i(300,250);
glVertex2i(350,250);
glEnd();
Any arbitrary quadrilateral (a four-sided polygon) can be drawn using
the GL_QUADS primitive. GL_QUADS works in a similar way to GL_LINES and GL_TRIANGLES - the
vertices specified between glBegin and glEnd are treated as groups of four, and used to draw filled
quadrilaterals. The following lines from 'drawshapes' display the two quadrilaterals (one square and one
irregular quadrilateral) at the top-right of the 'drawshapes' image.
glBegin(GL_QUADS);
glVertex2f(500.0, 400.0);
glVertex2f(530.0, 410.0);
glVertex2f(525.0, 365.0);
glVertex2f(490.0, 350.0);
glVertex2f(500.0, 350.0);
glVertex2f(550.0, 350.0);
glVertex2f(550.0, 300.0);
glVertex2f(500.0, 300.0);
glEnd();
GL_QUADS is a general primitive that can be used to draw any type of quadrilateral, including squares and
rectangles. However, there is another OpenGL routine that is only used for drawing rectangles. Consider the
following lines from the end of the display function in 'drawshapes'.
The glRecti routine draws the rectangle specified by the arguments provided. The first two arguments define
the x and y coordinates of the top-left corner of the rectangle, and the next two define the coordinates of its
bottom-right corner. You can also specify the coordinates as floating point values using glRectf. These lines
of code draw the two rectangles in the bottom-right of the image, one in black (which is the current
foreground colour to begin with) and one in grey. The second (grey) rectangle overwrites part of the first
(black) rectangle.
Step 1 − Find out the Ymin and Ymax from the given polygon.
Step 2 − ScanLine intersects with each edge of the polygon from Ymin to Ymax. Name each intersection
point of the polygon. As per the figure shown above, they are named as p0, p1, p2, p3.
Step 3 − Sort the intersection point in the increasing order of X coordinate i.e. (p0, p1), (p1, p2), and (p2,
p3).
Step 4 − Fill all those pair of coordinates that are inside polygons and ignore the alternate pairs.
Sometimes we come across an object where we want to fill the area and its boundary with different colors.
We can paint such objects with a specified interior color instead of searching for particular boundary color as
in boundary filling algorithm.
Instead of relying on the boundary of the object, it relies on the fill color. In other words, it replaces the
interior color of the object with the fill color. When no more pixels of the original interior color exist, the
algorithm is completed.
Once again, this algorithm relies on the Four-connect or Eight-connect method of filling in the pixels. But
instead of looking for the boundary color, it is looking for all adjacent pixels that are a part of the interior.
Boundary Fill Algorithm
The boundary fill algorithm works as its name. This algorithm picks a point inside an object and starts to fill
until it hits the boundary of the object. The color of the boundary and the color that we fill should be
different for this algorithm to work.
In this algorithm, we assume that color of the boundary is same for the entire object. The boundary fill
algorithm can be implemented by 4-connected pixels or 8-connected pixels.
Connected Polygon
In this technique 4-connected pixels are used as shown in the figure. We are putting the pixels above, below,
to the right, and to the left side of the current pixels and this process will continue until we find a boundary
with different color.
Algorithm
Step 1 − Initialize the value of seed point (seedx, seedy), fcolor and dcol.
Step 3 − Check if the current seed point is of default color, then repeat the steps 4 and 5 till the boundary
pixels reached.
If getpixel(x, y) = dcol then repeat step 4 and 5
Step 4 − Change the default color with the fill color at the seed point.
Step 5 − Recursively follow the procedure with four neighborhood points.
Connected Polygon
In this technique 8-connected pixels are used as shown in the figure. We are putting pixels above, below,
right and left side of the current pixels as we were doing in 4-connected technique.
In addition to this, we are also putting pixels in diagonals so that entire area of the current pixel is covered.
This process will continue until we find a boundary with different color.
Algorithm
Step 1 − Initialize the value of seed point (seedx, seedy), fcolor and dcol.
Step 2 − Define the boundary values of the polygon.
Step 3 − Check if the current seed point is of default color then repeat the steps 4 and 5 till the boundary
pixels reached
Step 4 − Change the default color with the fill color at the seed point.
Step 5 − Recursively follow the procedure with four neighbourhood points
Step 6 − Exit
The 4-connected pixel technique failed to fill the area as marked in the following figure which won’t happen
with the 8-connected technique.
Inside-outside Test
This method is also known as counting number method. While filling an object, we often need to identify
whether particular point is inside the object or outside it. There are two methods by which we can identify
whether particular point is inside an object or outside.
Odd-Even Rule
Nonzero winding number rule
Odd-Even Rule
In this technique, we will count the edge crossing along the line from any point (x,y) to infinity. If the
number of interactions is odd, then the point (x,y) is an interior point; and if the number of interactions is
even, then the point (x,y) is an exterior point. The following example depicts this concept.
From the above figure, we can see that from the point (x,y), the number of interactions point on the left side
is 5 and on the right side is 3. From both ends, the number of interaction points is odd, so the point is
considered within the object.
Nonzero Winding Number Rule
This method is also used with the simple polygons to test the given point is interior or not. It can be simply
understood with the help of a pin and a rubber band. Fix up the pin on one of the edge of the polygon and tie-
up the rubber band in it and then stretch the rubber band along the edges of the polygon.
When all the edges of the polygon are covered by the rubber band, check out the pin which has been fixed up
at the point to be test. If we find at least one wind at the point consider it within the polygon, else we can say
that the point is not inside the polygon.
In another alternative method, give directions to all the edges of the polygon. Draw a scan line from the point
to be test towards the left most of X direction.
Give the value 1 to all the edges which are going to upward direction and all other -1 as direction values.
Check the edge direction values from which the scan line is passing and sum up them.
If the total sum of this direction value is non-zero, then this point to be tested is an interior point, otherwise
it is an exterior point.
In the above figure, we sum up the direction values from which the scan line is passing then the total is 1 – 1
+ 1 = 1; which is non-zero. So the point is said to be an interior point.
Here is the Source Code with different algorithms discussed above
#include <GL/glut.h>
void myInit(void) {
glClearColor(1.0, 1.0,1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 640.0, 0.0, 480.0);
}
void display(void)
{
glColor3f(1.0, 0.0, 0.0); //Red color
//Draw only the edges of the polygons (wireframe rendering)
glPolygonMode (GL_FRONT, GL_LINE);
glBegin(GL_POLYGON);
glVertex2i(50, 250);
glVertex2i(100, 300);
glVertex2i(100, 340);
glVertex2i(10, 250);
glEnd( );
glColor3f(1.0, 1.0, 0.0); //Orange color
//fill the polygon faces
glPolygonMode (GL_FRONT, GL_FILL);
glBegin(GL_POLYGON);
glVertex2i(50, 150);
glVertex2i(100, 200);
glVertex2i(100, 240);
glVertex2i(10, 150);
glEnd( );
glColor3f(1.0, 0.0, 1.0); //Pink color
glPointSize(8);
//draw only the vertices of the polygons
glPolygonMode (GL_FRONT, GL_POINT);
glBegin(GL_POLYGON);
glVertex2i(50, 50);
glVertex2i(100, 100);
glVertex2i(100, 140);
glVertex2i(10, 50);
glEnd( );
glPolygonMode (GL_FRONT, GL_FILL);
glColor3f(0.0, 1.0, 0.0); //Green color
GLubyte fillPattern [ ] =
{ 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF };
//specify a fill pattern for polygons
glPolygonStipple(fillPattern);
glEnable(GL_POLYGON_STIPPLE);
glBegin(GL_POLYGON);
glVertex2i(350, 250);
glVertex2i(400, 300);
glVertex2i(400, 350);
glVertex2i(350, 400);
glVertex2i(300, 400);
glVertex2i(250, 350);
glVertex2i(250, 300);
glVertex2i(300, 250);
glEnd( );
glFlush( );
}
int main(int argc, char *argv[ ])
{
glutInit(&argc, argv);
glutInitWindowSize(640, 480);
glutInitWindowPosition(10, 10);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutCreateWindow("Fill Area attributes in OpenGL");
glutDisplayFunc(display);
myInit( );
glutMainLoop( );
}
}
void keyboard(unsigned char key, int x, int y){
switch(key){
case 27:// escape on keyboard
exit(0);
break;
case 97: // " a" on keyboard
switch(state){
case 1:
if(x_position<=7) x_position+=0.15;
else
state=-1;
break;
case -1:
if(x_position>-9) x_position-=0.15;
else
state=1;
break;
}
glutPostRedisplay();
break;
}
}
void mouse(int button,int s, int x, int y){
switch(button){
case GLUT_RIGHT_BUTTON:
exit(0);
break;
case GLUT_LEFT_BUTTON:
switch(state){
case 1:
if(x_position<=7) x_position+=0.15;
else
state=-1;
break;
case -1:
if(x_position>-9) x_position-=0.15;
else
state=1;
break;
}
glutPostRedisplay();
break;
}
}
void init(){
glClearColor(0.0,0.0,0.0,1.0);
}
int main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowPosition(200,200);
glutInitWindowSize(600,500);
glutCreateWindow("My First Tutorial");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
init();
glutMainLoop();
}
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, ‘a’);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, ‘a’);
In addition, we can change the colour of the character by using the glColor routine, as we have seen before.
To make other attribute changes, we must be using stroke character primitives.
Stroke character primitives are drawn using the glutStrokeCharacter routine. Using this type of character
primitive, we can change the font and colour as described above, and also the line width and the line style.
Remember that stroke characters are stored as set of line primitives. Therefore we can change the width of
these lines using the glLineWidth routine we introduced in Section Error: Reference source not found.
Similarly, we can change the style of the lines using the glLineStipple routine.
CHAPTER THREE
3. TRANSFORMATION
3.1 Translation