0% found this document useful (0 votes)
145 views

Computer Graphics Lab Manual For Promotion

This document provides a computer graphics laboratory manual for students. It contains instructions for setting up the OpenGL development environment in Dev C++. It introduces basic graphics primitives like points, lines, and polygons that can be drawn in OpenGL. It includes sample code to draw a single red point and explanations of OpenGL functions. The learning outcomes are to understand 3D graphics rendering using OpenGL and be able to model and manipulate 3D objects.

Uploaded by

Yibel Gashu
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
145 views

Computer Graphics Lab Manual For Promotion

This document provides a computer graphics laboratory manual for students. It contains instructions for setting up the OpenGL development environment in Dev C++. It introduces basic graphics primitives like points, lines, and polygons that can be drawn in OpenGL. It includes sample code to draw a single red point and explanations of OpenGL functions. The learning outcomes are to understand 3D graphics rendering using OpenGL and be able to model and manipulate 3D objects.

Uploaded by

Yibel Gashu
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 40

DEBRE MARKOS UNIVERSITY

DEBRE MARKOS INSTITUTE OF TECHNOLOGY


SOFTWARE ENGINEERING ACADEMIC PROGRAM
COMPUTER GRAPHICS LABORATORY MANUAL

PREPARED BY: - Yibeltal Gashu (BSC, Software Engineering)

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:

 Learn how to configure Dev C++ with OpenGL API.


 Learn how to use OpenGL to perform point, line generation and other geometrical artifacts.
 Learn how to use OpenGL to perform 3D translations and projections.
 Use OpenGL to manipulate lighting and shading.
 Know how colors are maneuvered in computer.
 Create interactive graphics applications.
 Understand the fundamental concepts of rendering with OpenGL.
 Model 3D objects using polygons.
 Understand non-polygon representation of objects and realize the difference between the above.
CHAPTER ONE
1. Definitions and Terminologies of Computer Graphics and Setting up
Working Environments
1.1 Definition
computer graphics refers to anything involved in the creation or manipulation of images on computer,
including animated images.

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 (Open Graphics Library) is a cross-platform, hardware-accelerated, language-independent,


industrial standard API for producing 3D (including 2D) graphics. Modern computers have dedicated GPU
(Graphics Processing Unit) with its own memory to speed up graphics rendering. OpenGL is the software
interface to graphics hardware. In other words, OpenGL graphic rendering commands issued by your
applications could be directed to the graphic hardware and accelerated.

We use 3 sets of libraries in our OpenGL 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.

1.2 Setting up the Environment


To start working with OpenGL we need to have install Dev C++ and integrate (set the path) glut libraries,
which are the API for Computer Graphics

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.

Now run Dev-C++ and create a new project.

Filenewproject 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.

1.3 Launch our first code


/*
*Tested under Dev-C++ OpenGL with the title MyFirstProject
* To compile with -lfreeglut -lglu32 -lopengl32
*/
#include <windows.h> // for MS Windows and cann ignore it
#include <GL/glut.h> // GLUT, include glu.h and gl.h

/* 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)

// Draw a Red 1x1 Square centered at origin


glPointSize(10);//Sets the size of the point to be drawn
glBegin(GL_POINTS); //start drawing a point with the following vertex and red color, we will discuss about
the color later.
glColor3f(1.0f, 0.0f, 0.0f); // Red, to set the color of the graphics primitives we use glColor3f(R,G,B) where R=red,
G=green, B=blue its limit is from 0 to 1;
glVertex2f(-0.5f, -0.5f); // x, y
glEnd();//stops drawing the primitives

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("OpenGL Setup Test"); // Create a 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 display callback handler for window re-paint
glutMainLoop(); // Enter the event-processing loop
return 0;
}

Output: -

Each part of the program will be explained in due course

OpenGL as a State Machine

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 initGL(), set the "clearing" or background color

glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // black and opaque

// 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!

1.4 Naming Convention for OpenGL Functions


An OpenGL functions:

 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 convention can be expressed as follows:

returnType glFunction[234][sifd] (type value, ...); // 2, 3 or 4 parameters

returnType glFunction[234][sifd]v (type *value); // an array parameter

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.

OpenGL defines its own data types:


 Signed Integers: GLbyte (8-bit), GLshort (16-bit), GLint (32-bit).

 Unsigned Integers: GLubyte (8-bit), GLushort (16-bit), GLuint (32-bit).

 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).

 GLsizei (32-bit non-negative integers).

 GLenum (32-bit enumerated integers).

The OpenGL types are defined via typedef in "gl.h" as follows:

typedef unsigned int GLenum;

typedef unsigned char GLboolean;

typedef unsigned int GLbitfield;

typedef void GLvoid;

typedef signed char GLbyte; /* 1-byte signed */

typedef short GLshort; /* 2-byte signed */

typedef int GLint; /* 4-byte signed */

typedef unsigned char GLubyte; /* 1-byte unsigned */

typedef unsigned short GLushort; /* 2-byte unsigned */

typedef unsigned int GLuint; /* 4-byte unsigned */

typedef int GLsizei; /* 4-byte signed */

typedef float GLfloat; /* single precision float */

typedef float GLclampf; /* single precision float in [0,1] */

typedef double GLdouble; /* double precision float */

typedef double GLclampd; /* double precision float in [0,1] */

OpenGL's constants begins with "GL_", "GLU_" or "GLUT_", in uppercase separated with underscores, e.g.,
GL_COLOR_BUFFER_BIT.

For examples,

glVertex3f(1.1f, 2.2f, 3.3f); // 3 GLfloat parameters


glVertex2i(4, 5); // 2 GLint paramaters
glColor4f(0.0f, 0.0f, 0.0f, 1.0f); // 4 GLfloat parameters
GLdouble aVertex[] = {1.1, 2.2, 3.3};
glVertex3fv(aVertex); // an array of 3 GLfloat values

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

2.2 Drawing Points


In OpenGL, an object is made up of geometric primitives such as triangle, quad, line segment and point.
A primitive is made up of one or more vertices.

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>

The header "windows.h" is needed for the Windows platform only.

#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().

void glutInit(int *argc, char **argv)

 glutCreateWindow: creates a window with the given title.

int glutCreateWindow(char *title)

 glutInitWindowSize: specifies the initial window width and height, in pixels.

void glutInitWindowSize(int width, int height)


 glutInitWindowPosition: positions the top-left corner of the initial window at (x, y). The coordinates
(x, y), in term of pixels, is measured in window coordinates, i.e., origin (0, 0) is at the top-left corner
of the screen; x-axis pointing right and y-axis pointing down.

void glutInitWindowPosition(int x, int y)

 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.

void glutDisplayFunc(void (*func)(void))

 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()

One-time Initialization initGL()

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().

 Callback Handler display()

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.

In the main() function of the example:


glutInit(&argc, argv);

glutCreateWindow("Vertex, Primitive & Color");

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.

void glColor3f(GLfloat red, GLfloat green, GLfloat blue)

void glColor3fv(GLfloat *colorRGB)

void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)

void glColor4fv(GLfloat *colorRGBA)

void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)

// GLclampf in the range of 0.0f to 1.0f

Notes:

 Color is typically specified in float in the range 0.0f and 1.0f.


 Color can be specified using RGB (Red-Green-Blue) or RGBA (Red-Green-Blue-Alpha)
components. The 'A' (or alpha) specifies the transparency (or opacity) index, with value of 1 denotes
opaque (non-transparent and cannot see-thru) and value of 0 denotes total transparent.

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 initGL(), set the "clearing" or background color

glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black and opague background color

In display(), we set the vertex color via glColor3f for subsequent vertices. For example, R=1, G=0, B=0
(red).

// In display(), set the foreground color of the pixel

glColor3f(1.0f, 0.0f, 0.0f); // Red

A geometric primitive is defined by specifying its vertices via glVertex function, enclosed within a pair
glBegin and glEnd.

void glBegin(GLenum shape)

void glVertex[234][sifd] (type x, type y, type z, ...)

void glVertex[234][sifd]v (type *coords)

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.

In the above example:


glBegin(GL_POINTS);

one point with 1x1 glVertex(); function.

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?

2.3 Drawing Lines, Line Strip and Line Loop


The first new primitive we see is GL_LINES. When you run the program, the following lines draw the cross
at the bottom-left of the window.

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.

Let’s try it: -

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.

Line Style and Width

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);

Use the following extra example for further clarification.

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);

glLineStipple (1, 0x00FF);// Plot a dash-dot, standard-width polyline.

glColor3f(0,1,0);

glBegin(GL_LINES);

glVertex2i(50,100);

glVertex2i(450,450);

glEnd( );

glEnable(GL_LINE_STIPPLE);

glLineWidth(3);

glLineStipple (1, 0x00FF); // Plot a dashed, double-width polyline.

glColor3f(1,1,0);

glBegin(GL_LINES);

glVertex2i(50,50);

glVertex2i(450,400);
glEnd( );

glLineStipple (1, 0x0101); // Plot a dotted, triple-width polyline.

glColor3f(1,0,0);

glBegin(GL_LINES);

glVertex2i(100,50);

glVertex2i(500,400);

glEnd( );

glEnable(GL_LINE_STIPPLE);

glFlush( ); // send all output to the display

2.4 Drawing Triangle, Triangle strip and Triangle Fan

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( );

2.5 Drawing a Circle

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

The equation of circle is X2+Y2=r2 , X2


+Y2=r2, where r is radius.
2.5.1 Bresenham’s Algorithm

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.

 If d <= 0, then N(X+1, Y) is to be chosen as next pixel.

 If d > 0, then S(X+1, Y-1) is to be chosen as the next pixel.

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.

Step 2 − Set decision parameter D = 3 – 2R.

Step 3 − Repeat through step-8 while P ≤ Q.

Step 4 − Call Draw Circle (X, Y, P, Q).

Step 5 − Increment the value of P.

Step 6 − If D < 0 then D = D + 4P + 6.

Step 7 − Else Set R = R - 1, D = D + 4(P-Q) + 10.

Step 8 − Call Draw Circle (X, Y, P, Q).

Here is the full source code: -

#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();

2.6 Drawing Polygons


The GL_POLYGON primitive takes a sequence of vertices and draws the corresponding filled polygon. The
polygon must be convex - a polygon is convex if a line connecting any two points of the polygon lies entirely
within it. If a non-convex polygon is specified, the closest convex polygon will be drawn instead. If you want
to draw a filled non-convex polygon you must draw a polygon outline using GL_LINE_STRIP and then fill it
using an algorithm such as flood fill.

The lines shown below draw the filled hexagon.

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'.

glRecti(500, 100, 580, 140);


glColor3f(0.5,0.5,0.5);
glRecti(520, 120, 610, 150);

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.

2.6.1 Polygon filling Algorithms


Scan Line Algorithm
This algorithm works by intersecting scanline with polygon edges and fills the polygon between pairs of
intersections. The following steps depict how this algorithm works.

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.

Flood Fill Algorithm

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 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.
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.

tep 6 − Exit


There is a problem with this technique. Consider the case as shown below where we tried to fill the entire
region. Here, the image is filled only partially. In such cases, 4-connected pixels technique cannot be used.

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( );
}

2.7 Other Callback Functions


Keyboard callback Function
glutKeyboardFunc(mykey)
void mykey(unsigned char key,
int x, int y)
Returns ASCII code of key depressed and mouse location
void mykey()
{
if(key == ‘Q’ | key == ‘q’)
exit(0);
}
GLUT defines the special keys in glut.h
Function key 1: GLUT_KEY_F1
Up arrow key: GLUT_KEY_UP
if(key == ‘GLUT_KEY_F1’ ……
Can also check if one of the modifiers
GLUT_ACTIVE_SHIFT
GLUT_ACTIVE_CTRL
GLUT_ACTIVE_ALT
is depressed by
glutGetModifiers()
Allows emulation of three-button mouse with one- or two button mice

The Reshape callback


it uses the glut function glutReshapeFunc(myreshape) and the method is void myreshape( int w, int h)
returns width and height of new window (in pixels)
A redisplay is posted automatically at end of execution of the callback
 GLUT has a default reshape callback but you probably want to define your own
 The reshape callback is a good place to put viewing functions because it is invoked when the window is
first opened.
Example Reshape
 This reshape preserves shapes by making the viewport and world window have the same aspect ratio
void myReshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); /* switch matrix mode */
glLoadIdentity();
if (w <= h)
gluOrtho2D(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w);
else gluOrtho2D(-2.0 * (GLfloat) w / (GLfloat) h, 2.0 *
(GLfloat) w / (GLfloat) h, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW); /* return to modelview mode */
}

The mouse Callback


It uses the function glutMouseFunc(mymouse) and the method should be void mymouse(GLint button,
GLintstate, GLint x, GLint y)
Returns which button (GLUT_LEFT_BUTTON,
GLUT_MIDDLE_BUTTON,
GLUT_RIGHT_BUTTON) caused event
 state of that button (GLUT_UP, GLUT_DOWN)
 Position in window
Positioning
The position in the screen window is usually measured in pixels with the origin at the top-left
corner.Consequence of refresh done from top tobottom. OpenGL uses a world coordinate system
with origin at the bottom left. Must invert y coordinate returned by callback by height of window
• y = h – y;
(0,0)
Obtaining the Window Size To invert the y position we need the window height. Height can change during
program execution Track with a global variable New height returned to reshape callback that we will look at
in detail soon
 Can also use query functions glGetIntv glGetFloatv to obtain any value that is part of the state
 We can use the simple mouse callback
void mouse(int btn, int state, int x, int y)
{
if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)
exit(0);
And here is further example for mouse and keyboard function:-
#include <windows.h>
#include<GL/glut.h>
float x_position=0.0;
int state=1;
void reshape(int h, int w){
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-10,10,-10,10);
glMatrixMode(GL_MODELVIEW);
}
void display(){
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glBegin(GL_TRIANGLES);
glColor3f(1.0,0.0,0.0);
glVertex2f(x_position+1,0);
glColor3f(0.0,1.0,0.0);
glVertex2f(x_position+4,0);
glColor3f(1.0,1.0,0.0);
glVertex2f(x_position+2,3);
glEnd();
glFlush();

}
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();
}

Opengl Character Attributes


Recall that in OpenGL bitmap characters are drawn using the glutBitmapCharacter routine. For bitmap
characters we can change the font by changing the first argument to this function, e.g.

glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, ‘a’);

will write the letter ‘a’ in 10-point Times-Roman font, whereas

glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, ‘a’);

will draw the same letter in 10-point Helvetica font.

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

You might also like