Computer Graphics
using openGL
Dr Mohamed Abdou Mohamed
Getting Started
Graphics Commands use a coordinate system that is attached to the
window
Window - based
What Is OpenGL?
• OpenGL is a software interface to graphics
hardware. You can use to specify the objects
and operations needed to produce interactive
three-dimensional applications
• OpenGL is designed as a hardware-independent
interface to be implemented on many different
hardware platforms.
Graphics Library
• Primitives: lines, circles, ellipses, polygons,
filling, clipping
• Attributes
– Color
– Line style
– Material properties for 3D
• Lights
• Transformations
OpenGL (1/3)
• The most popular raster graphics library, providing a
powerful but primitive set of rendering commands
• Already supported by every window systems
• OpenGL Utility Library (GLU) : higher-level routines, part
of OpenGL implementation
– Setting up matrices for specific viewing orientations
and projections
– Performing polygon tessellation and rendering
surfaces
• OpenGL Utility Toolkit (GLUT): window-system-
independent high-level library. Need to install this library
separately.
OpenGL (2/3)
• Install OpenGL Utility Toolkit (GLUT) for MS Windows
– Download GLUT from
http://reality.sgi.com/opengl/glut3/glut3.html
– Unzip the package
– Set “include directory” and “lib directory” in the C
Compiler to include the directory containing glut.h,
glut.lib
– Copy glut32.dll into directory
DRIVE:\WINNT\SYSTEM
• Add #include <glut.h> to the beginning of the program
OpenGL (3/3)
• OpenGL Programming Guide:
– http://www.cs.ucf.edu/dsg/dtran/teaching/cps5
60/openGL/install/theredbook.zip
• Nate Robins’ OpenGL Tutors
–
http://www.cs.utah.edu/~narobins/opengl.html
GLUT
GLUT stands for OpenGL Utility Toolkit.
In order to write a C++ application using GLUT you'll
need three files:
1- glut.h - You'll have to include This is the file in your
source code. The common place to put this file is in
C:\Program Files\Microsoft Visual Studio\VC98\Include\GL
folder.
2- glut.lib and glut32.lib
This file must be linked to your application so make sure
to put it your lib folder.
3- glut32.dll and glut.dll - choose one according to the
OpenGL you're using. If using Microsoft's version then
you must choose glut32.dll. You should place the dll
file in your system folder.
SETUP
In the "Project options" textbox replace
"subsystem:console" The following files to the Object/library
modules: opengl32.lib glut32.lib glu32.lib
with
"subsystem:windows"
Programming with Open GL
1- Initialization
• All the functions in GLUT have the prefix glut, and
those which perform some kind of initialization have
the prefix glutInit .
• The first thing you must do is call the function
glutInit .
void glutInit(int *argc, char **argv);
Parameters: argc argv are the standard ones for
passing information about the command line ( not
used here)
Define our window
• After initializing GLUT itself, we're going to define our window.
• First we establish the window's position, i.e. its top left corner.
In order to do this we use the function glutInitWindowPosition .
void glutInitWindowPosition(int x, int y);
glutInitWindowPosition( 100, 150);
Parameters:
• x - the number of pixels from the left of the screen.
• y - the number of pixels from the top of the screen.
Window size
• Next we'll choose the window size. In order to do this
we use the function glutInitWindowSize .
void glutInitWindowSize(int width, int height);
glutInitWindowSize(640, 480);
Parameters:
• width - The width of the window
• height - the height of the window
• The values for width and height are only a suggestion, so
avoid choosing negative values.
• When the program is running the user can resize the window
Display mode
• Then you should define the display mode using the
function
glutInitDisplayMode
void glutInitDisplayMode(unsigned int mode)
Parameters:
• mode - specifies the display mode
You use mode to specify the color mode, and the number and
type of buffers.
Examples:
• GLUT_RGBA or GLUT_RGB - selects a RGBA window. This
is the default color mode.
• GLUT_INDEX - selects a color index mode.
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE );
• After all the above steps, the window can be created with
glutCreateWindow
• int glutCreateWindow(char *title);
Parameters:
• title - sets the window title
glutCreateWindow(“my first attempt");
#include <windows.h>
#include <GL/GL.h>
#include <GL/GLU.h>
#include <GL/glut.h>
void main (int argc, char ** argv)
{
glutInit(&argc, argv); // initialize the toolkit
// set the display mode
glutInitDisplayMode(GLUT_SINGLE| GLUT_RGB);
// set window size
glutInitWindowSize(640,480);
// open the screen window
glutInitWindowPosition(100,150);
glutCreateWindow("my firstattempt");
}
Making Pictures
• Step One: Initialisation
– Setting up the graphics display.
1. Entire Screen is used (computer games, slide shows)
Making Pictures
• Step One: Initialisation
– Setting up the graphics display.
2. Window-based (upside down coordinates) (when multiple
windows are useful, paint packages, word processing,
graphing)
Making Pictures
• Step One: Initialisation
– Setting up the graphics display.
3. Window-based (right side up coordinates) (an
alternative more natural representation)
Making Pictures
OpenGL – Inverted Windows
glutInitWindowSize(640,480);
void gluOrtho2D( GLdouble left,
glutInitWindowPosition(100, 150);
GLdouble right,
glutCreateWindow(“An OpenGL Window");GLdouble bottom ,
GLdouble top)
gluOrtho2D(0.0, 640.0, 480.0, 0.0);
void gluOrtho2D (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top);
Creates a matrix for projecting two -dimensional coordinates onto the screen and
multiplies the current projection matrix by it. The clipping reg ion is a rectangle with
the lower -left corner at (left, bottom) and the upper -right corner at (right, top).
Making Pictures
OpenGL – Inverted Windows
Window size = 640 x 480
(0,0)
(100,410)
(640,480)
Making Pictures
OpenGL – “Right-side Up” Windows
glutInitWindowSize(640,480);
glutInitWindowPosition(100, 150);
glutCreateWindow(“An OpenGL Window");
gluOrtho2D(0.0, 640.0, 0.0, 480.0);
Making Pictures
OpenGL – “Right-side Up” Windows
Window size = 640 x 480
(0,480)
(100,410)
(640,0)
#include <windows.h>
#include <GL/GL.h> Skeleton program
#include <GL/GLU.h>
#include <GL/glut.h>
void myInit(void)
{
glClearColor(1.0,1.0,1.0,0.0); // set white background color
glColor3f(0.0f, 0.0f, 0.0f); // set drawing color
glPointSize(8.0); // the dot is 8 by 8 pixels
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,640,480,0);
}
void myDisplay(void) // The name is option
{
/* code written here*l
}
void main (int argc, char ** argv)
{
glutInit(&argc, argv); // initialize the toolkit
// set the display mode
glutInitDisplayMode(GLUT_SINGLE| GLUT_RGB);
// set window size
glutInitWindowSize(640,480);
// open the screen window
glutInitWindowPosition(100,150);
glutCreateWindow("my firstattempt");
myInit(); // additional initializations as necessary
// register callback functions
glutDisplayFunc(myDisplay);
glutMainLoop();
}
GLUT provides a function that gets the application in a never ending
loop, always waiting for the next event to process. The GLUT
function is glutMainLoop ,
If you run this code, you'll obtain an empty black console window.
Furthermore after a few seconds the window disappears.
Example 1:
The function presented bellow will clear the color buffer and draw 3 points.
void myDisplay(void) // The name of this //function is up to you
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POINTS);
glVertex2i(100,50);
glVertex2i(100,130);
glVertex2i(150,130);
glEnd();
glFlush(); // send all output to display
}
The openGL function that will call our implemented myDisplay function is
void glutDisplayFunc(void (*func)(void));
Parameters:
func - the name of the function to be called when the window needs to be
redrawn.
In our example myDisplay
glutDisplayFunc(myDisplay);
Example 2:
The function presented bellow will clear the color
buffer and draw a triangle.
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0.0);
glVertex3f(0.5,0.0,0.0);
glVertex3f(0.0,0.5,0.0);
glEnd();
glFlush();
}
Do not forget to add the following line to your code
glutDisplayFunc(renderScene);
The constant GL_POINTS is built-into OpenGL. to draw other primitives, you
replace GL_POINTS with GL_LINES, GL_POLYGON, etc.
glColor3f()
glVertex2i(…)
Void drawDot(GLint x , GLint y)
{// draw dot at integer point (x, y)
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
is better than the function written as
Void drawDot(int x , int y) //Danger writting
{// draw dot at integer point (x, y)
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
glPointSize(3.0) ; // the size of drawing point is 3 x 3 pixels
glColor3f(1.0, 0.0, 0.0); // drawing is red
glColor3f(0.0, 1.0, 0.0); // drawing is green
glColor3f(0.0, 0.0, 1.0); // drawing is blue
glColor3f(0.0, 0.0, 0.0); // drawing is black
glColor3f(1.0, 1.0, 1.0); // drawing is white
#include <windows.h>
#include <GL/GL.h>
#include <GL/GLU.h>
Example 3
#include <GL/glut.h>
class GLintPoint{
public:
GLint x, y;
};
int random (int m)
{
return rand()%m;
}
void myInit(void)
{
glClearColor(1.0,1.0,1.0,0.0); // set white background color
glColor3f(0.0f, 0.0f, 0.0f); // set drawing color
glPointSize(8.0); // the dot is 8 by 8 pixels
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,640,480,0);
}
void drawDot(GLint x , GLint y)
{// draw dot at integer point (x, y)
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
void Sierpinski(void) // The name of this function is upto you
{
GLintPoint T[3] = {{10,10} , {300,30} , {200, 300}};
int index = random(3); // 0, 1, 2 equally likely
glClear(GL_COLOR_BUFFER_BIT);
GLintPoint point = T[index] ; // initial point (10,10) or (300,30) or (200, 300)
drawDot(point.x, point.y); // draw initial point
for(int i=0; i< 1000; i++) // raw 1000 dots
{
index = random(3);
point.x=(point.x +T[index].x) / 2;
point.y=(point.y +T[index].y) / 2;
drawDot(point.x, point.y);
}
glFlush(); // send all output to display
}
void main (int argc, char ** argv)
{
glutInit(&argc, argv); // initialize the toolkit
// set the display mode
glutInitDisplayMode(GLUT_SINGLE| GLUT_RGB);
glutInitWindowSize(640,480); // set window size
glutInitWindowPosition(100,150); // open the screen window
glutCreateWindow("my Sierpinski");
// register callback functions
glutDisplayFunc(Sierpinski);
myInit(); // additional initializtons as necessary
glutMainLoop();
}
A dot plot of function
#include <windows.h>
#include <math.h> Example 4
#include <GL/GL.h>
#include <GL/GLU.h>
#include <GL/glut.h>
const int screenWidth = 640;
const int screenHeight = 480;
GLdouble A,B,C,D;
void myInit(void)
{
glClearColor(1.0,1.0,1.0,0.0); // set white background color
glColor3f(0.0f, 0.0f, 0.0f); // set drawing color
glPointSize(4.0); // the dot is 4 by 4 pixels
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble) screenWidth,0.0, (GLdouble) screenHeight);
A = screenWidth / 4.0 ;
B = 0.0;
C = D = screenHeight /2.0;
}
void dotplotfunction(void) // The name of this function
is upto you
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POINTS);
for (GLdouble x = 0; x< 4.0; x+=0.005)
{
GLdouble func = exp(-x) * cos(2*3.14159265 * x);
glVertex2d(A * x + B , C * func + D);
}
glEnd();
glFlush(); // send all output to display
}
A = screenWidth / 4.0 ; // x 0 …4
d double B = 0.0;
C = D = screenHeight /2.0;// y 1… -1
void main (int argc, char ** argv)
{
// initialize the toolkit
glutInit(&argc, argv);
// set the display mode
glutInitDisplayMode(GLUT_SINGLE| GLUT_RGB);
// set window size
glutInitWindowSize(640,480);
// set window position
glutInitWindowPosition(100,150);
// open the screen window
glutCreateWindow("Dot plot of function");
// register callback functions
glutDisplayFunc(dotplotfunction);
myInit(); // additional initializtons as necessary
glutMainLoop();
}
Making Line Drawings
• Use GL_LINES as the argument to glBegin(), and pass it the
two end points as vertices.
void drawLineInt ( GLint x1, GLint y1, Glint x2, Glint y2)
{
glBegin(GL_LINES);
glVertex2i(x1, y1); Example 5
glVertex2i(x2, y2);
glEnd();
}
Simple picture built from four lines.
If more than two vertices are specified between
glBegin(GL_LINES) and glEnd (), they are taken in
pairs, and a separate line is drawn between each pair.
would be drawn using the following commands:
glBegin(GL_LINES) ;
glVertex2i(10, 20) ; // first horizontal line
glVertex2i(40, 20) ;
glVertex2i(20, 10) ; // first vertical line
glVertex2i(20, 40) ;
// calls to to glVertex2i() here for the other two lines
glEnd() ;
gIFlush() ;
• A line's color is set in the same way as that for points,
using glColor3f().
• Thick of lines are set by gILineWidth (4.0). The default
thickness is 1.0.
#include <windows.h>
#include <math.h>
#include <GL/GL.h>
#include <GL/GLU.h>
#include <GL/glut.h>
const int screenWidth = 640;
const int screenHeight = 480;
GLdouble A,B,C,D;
void myInit(void)
{
// set white background color
glClearColor(1.0,1.0,1.0,0.0);
// set drawing color
glColor3f(0.0f, 0.0f, 0.0f);
// the line width is 4 pixels
glLineWidth(4.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble) screenWidth, 0.0, (GLdouble) screenHeight);
}
void myDisplay(void) // The name of this function is up
to you
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES) ;
glVertex2i(100, 200) ; // first horizontal line
glVertex2i(400, 200) ;
glVertex2i(200, 100) ; // first vertical line
glVertex2i(200, 400) ;
glVertex2i(100, 300) ; // Second horizontal line
glVertex2i(400, 300) ;
glVertex2i(300, 100) ; // Second vertical line
glVertex2i(300, 400) ;
glEnd() ;
glFlush() ; // send all output to display
}
void main (int argc, char ** argv)
{
glutInit(&argc, argv); // initialize the toolkit
// set the display mode
glutInitDisplayMode(GLUT_SINGLE| GLUT_RGB);
glutInitWindowSize(640,480); // set window size
// open the screen window
glutInitWindowPosition(100,150);
glutCreateWindow(“Lines Plot");
// register callback functions
glutDisplayFunc(myDisplay);
myInit(); // additional initializtons as necessary
glutMainLoop();
}
Drawing Polylines and Polygons
Polyline is a collection of line segments joined end to end. It is described
by an ordered list of points, as in the equation
po = (xo,yo), p1 = (x1, y1), ...,pn = (xn, yn).
In OpenGL, a polyline is called a "line strip" and is drawn by specifying the
vertices,in turn, between gIBegin (GL_LINE_STRIP) and glEnd ().
For example, the code
glBegin(GL_LINE_STRIP); // draw an open polyline
glVertex2i(20,10);
glVertex2i(50,10) ;
glVertex2i(20,80);
glVertex2i(50,80) ;
glEnd();
gIFlush() ;
produces the polyline shown
If it is desired to draw polygon, simply replace GL_LINE_STRIP with GL_LINE_LOOP
• Polygons drawn using GL_LINE_LOOP cannot be filled with a color or
pattern.
• To draw filled polygons, you must use
gIBegin (GL_POLYGON).
EXAMPLE 2.3.1 Drawing line graphs
• A plot of a mathematical formula.
The process of plotting a function with line segments is almost identical
to that for producing a dot plot, so the program of Figure 2.16 can be
used with only slight adjustments.
We must scale and shift the lines being drawn here, to properly place
them in the window. This requires the computation of the constants A, B,
C, and D in the same manner as we did before.
Most interesting pictures made up of polylines contain a
rather large number of lines segments. It is convenient to
store a description of polylines in a file, so that the
picture can be redrawn at will.
Parameterizing figures
• Figure 2.23 shows a simple house consisting of a few
polylines. It can be drawn using code shown partially in
the following
void hardwiredHouse(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINE_LOOP);
glVertex2i(40, 40); // draw the shell of house
glVertex2i(40, 90);
glVertex2i(70, 120);
glVertex2i(100, 90);
glVertex2i(100, 40);
glEnd() ;
glBegin(GL_LINE_STRIP);
glVertex2i(50, 100); // draw the chimney
glVertex2i(50, 120);
glVertex2i(60, 120);
glVertex2i(60, 110);
glEnd() ;
glBegin(GL_LINE_STRIP);
glVertex2i(55, 40); // draw the door
glVertex2i(55, 80);
glVertex2i(70, 80);
glVertex2i(70, 40);
glEnd() ;
glBegin(GL_LINE_LOOP);
glVertex2i(80, 75); // draw the window
glVertex2i(80, 85);
glVertex2i(90, 85);
glVertex2i(90, 75);
glEnd() ;
}
•This is not a very flexible approach. The position of each
endpoint is hardwired into the code, so hardwirededHouse ()
can draw only one house in one size and one location.
FIGURE 2.26 A "village" of houses drawn
usingparameterizedHouse().
•This routine may be used to draw a "village," as shown in
Figure 2.26, by mak-ing successive calls to
parameterizedHouse () with different parameter values.
(How is a house "flipped" upside down? Can all of the
houses in the figure be drawn using the routine given?)
void parameterizedHouse(GLintPoint peak, GLint width, GLint height)
// the top of house is at the peak; the size of house is given
// by the height and width
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINE_LOOP);
glVertex2i(peak.x,peak.y); // draw shell of house
glVertex2i(peak.x + width / 2, peak.y - 3 * height /8);
glVertex2i(peak.x + width / 2, peak.y - height);
glVertex2i(peak.x - width / 2, peak.y - height);
glVertex2i(peak.x - width / 2, peak.y - 3 * height /8);
glEnd();
glBegin(GL_LINE_STRIP);
// draw the chimney •The parameters specify the location of
glEnd() ; the peak of the roof and the width and
height of the house.
glBegin(GL_LINE_STRIP); The details of drawing the chimney, door,
// draw the door
glEnd() ;
and window are left as an exercise.
glBegin(GL_LINE_LOOP);
// draw the window
glEnd() ;
glFlush();
}
#include <windows.h>
#include <math.h>
#include <GL/GL.h>
#include <GL/GLU.h>
#include <GL/glut.h>
int random (int m)
{
return rand()%m;
}
class GLintPoint{
public:
GLint x, y;
};
const int screenWidth = 640;
const int screenHeight = 480;
//<<<<<<<<<<<<<<<<<<<< myInit >>>>>>>>>>>>>>>>>>
void myInit(void)
{
glClearColor(1.0,1.0,1.0,0.0); // set white background color
glColor3f(0.0f, 0.0f, 0.0f); // set drawing color
glLineWidth(1.0); // the line width is 4 pixels
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble) screenWidth,0.0, (GLdouble)
screenHeight);
}
//<<<<< parameterizedHouse >>>>>>>>>>>>>>
void parameterizedHouse(GLintPoint peak, GLint width, GLint height)
// the top of house is at the peak; the size of house is given
// by the height and width
{
// the code written here
}
//<<<<<<<<<< myDisplay >>>>>>>>
void myDisplay(void)
{
GLintPoint point;
int width, height;
// make successive calls to parameterizedHouse
}
//<<<<<<< main >>>>>>>>>
void main (int argc, char ** argv)
{
// code written here
}
EXAMPLE 2.3.4 Building a polyline drawer
• Some applications compute and store the vertices of a
polyline in a list. We have to add to our growing toolbox
of routines a function that accepts the list as a parameter
and draws the corresponding polyline.
• The list might be in the form of an array or a linked list.
• Here we use the array form and define the class to hold
it in
class GLintPointArray
{
const int MAX_NUM = 100;
public:
int num;
GLintPoint pt [MAX_NUM];
}
pt is an array of GLintPoint
num is the actual number of elements in the array
void drawPolyLine ( GLintPointArray poly, int closed)
{
gIBegin ( closed ? GL_LINE_LOOP : GL_LINE_STRIP);
for(int i = 0; i < poly.num; i++)
glVertex2i(poly.pt[i].x, poly.pt[i].y);
glEnd();
gIFlush() ;
}
// pt is an array of GLintPoint
// num is the actual number of elements in the array
• The routine also takes a parameter closed:
If closed is nonzero, the GL_LINE_LOOP passed to OpenGL
• The routine simply sends each vertex of the polyline to OpenGL
Line Drawing using moveto () and lineto()
• We can summarize the effects of the two functions as
follows:
• moveto (x, y): set CP to (x, y)
CP is the current position
• lineto (x, y): draw a line from CP to (x, y), and then
update CP to (x, y)
A line from (x1, y1) to (x2, y2) is therefore drawn using the
two calls moveto (x1, y1) and lineto (x2 , y2).
A polyline based on the list of points, so it is easily drawn
using the following code:
moveto(x[0], y [0]);
for ( int i =1; i < n; i++)
lineto ( x[i], y[i]);
moveto() and lineto()
in OpenGL.
GLintPoint CP; // global current position
//«««««« moveto »»»»»»»
void moveto(GLint x, GLint y)
{
CP.x = x; CP.y = y; // update the CP )
}
//«««««« lineTo >»»»»»»»»
void lineto(GLint x, GLint y)
{
glBegin(GL_LINES); // draw the line glVertex2i(CP.x, CP.y);
glVertex2i(x, y);
glEnd();
gIFlush() ;
CP.x = x; CP.y = y; // update the CP
}
Drawing Aligned Rectangles
A special case of a polygon is the aligned rectangle, so called
because its sides are aligned with the coordinate axes. You just
need two points to draw it.
// white background
glClearColor(l.0,1.0,1.0,0.0);
// clear window
glClear(GL_COLOR_BUFFER_BIT); //
// filled color is bright gray
glColor3f(0.6,0.6,0.6);
// draw the rectangle
glRecti(20,20,100,70);
// filled color is dark gray
glColor3f(0.2,0.2,0.2);
// draw the rectangle
glRecti(70, 50, 150, 130) ;
glFlush();
Part (a) is a "flurry" of randomly chosen aligned rectangles that might be
generated by code such as the following
void drawFlurry(int num, int numColors, int Width, int Height)
// draw num random rectangles in a Width by Height rectangle
{
for (int i = 0; i < num; i++)
{
Glint x1 = random(Width); // place corner randomly
GLint y1 = random(Height);
Glint x2 = random(Width); // pick the size so it fits
GLint y2 = random(Height);
GLfloat lev = random(10)/10.0 // random value, in range 0 to 1
glColor3f(lev,lev,lev); //set the gray level of drawing
gIRecti (x1 , y1 , x2 , y2) ; // draw the rectangle
}
glFlush();
}
void drawChessBoard(int size)
// draw num random rectangles in a Width by Height rectangle
{
GLfloat lev1 = random(10)/10.0; //value, in range 0 to 1
GLfloat lev2 = random(10)/10.0; // value, in range 0 to 1
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
{
GLint x1 = i * size ; // place 1st corner
GLint y1 = j * size ;
GLint x2 = i * size + size; // place 2nd corner
GLint y2 = j * size + size;
if ((i+j) % 2 == 0) // if i+j is even
glColor3f(lev1,lev1,lev1);
else
glColor3f(lev2,lev2,lev2);
glRecti (x1 , y1 , x2 , y2) ; // draw the rectangle
}
glFlush();
}
//<<<<<<<<<<<<<<< DrawDiamond >>>>>>>>>>>>>>>>>>>>>>>>>>
void DrawDiamond(GLintPoint center, int d)
// draw num random rectangles in a Width by Height rectangle
{
int x0 = center.x ; // calculate center
int y0 = center.y ;
glBegin(GL_LINE_LOOP);
glVertex2i(x0-d,y0);
glVertex2i(x0,y0-d);
glVertex2i(x0+d,y0);
glVertex2i(x0,y0+d);
glEnd();
glFlush();
}
//<<<<<<<<<<<<<<< myDisplay >>>>>>>>>>>>>>>>>>>>>>>>>>
void myDisplay(void) // The name of this function is upto you
{
GLintPoint CenterPoint;
int const size = 40;
CenterPoint.x = screenWidth /2;
CenterPoint.y = screenHeight /2;
glClear(GL_COLOR_BUFFER_BIT);
DrawDiamond(CenterPoint, size) ;
glFlush(); // send all output to display
}
To draw a convex polygon
based on vertices use the usual list of vertices, but place them between a
glBegin(GL_POLYGON) and a glEnd ():
glBegin(GL_POLYGON);
glVertex2f(xo, yo);
glVertex2f(x1, y1);
.
.
glVertex2f(xn, yn);
glEnd();
The polygon will be filled in the current color. It cart also be filled with a
stipple pattern (see Case Study 2.5),
Other Graphics Primitives in OpenGL
GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN
•GL_TRIANGLES: takes the listed vertices three at a time and draws a separate
triangle for each.
• GL_TRIANGLE_STRIP: draws a series of triangles based on triplets of vertices:
vo, v1, v2,, then v1, v2, v3, then v2, v3, v4., etc. (in an order such that all triangles
are "traversed" in the same way, e.g., counterclockwise).
•GL_TRIANGLE_FAN: draws a series of connected triangles based on triplets of
vertices: vo, v1, v2, then vo, v2, v3, then vo, v3, v4., etc.
GL_QUADS GL_QUAD_STRIP
• GL_QUADS: takes the vertices four at a time and draws a separate
quadrilateral for each.
• GL_QUAD_STRIP: draws a series of quadrilaterals based on
foursomes of vertices: first vo, v1, v2,v3, then vo, v1 , v3, v2, then
v2, v3, v5, v4, then v4, v5, v7, v6., etc. (in an order such that all
quadrilaterals are "traversed" in the same way, e.g.,
counterclockwise).
SIMPLE INTERACTION WITH THE MOUSE AND KEYBOARD
• when the user presses or releases a mouse button, moves the mouse,
or presses a keyboard key, an event occurs. Using the OpenGL Utility
Toolkit (GLUT) the programmer can register a callback function with
each of these events by using the following commands:
• glutMouseFunc (myMouse),
which registers myMouse () with the event that occurs when the mouse
button is pressed or released;
• void myMouse(int button, int state, int x, int y);
• glutMotionFunc (myMovedMouse)
which registers myMovedMouse () with the event that occurs when the
mouse is moved while one of the buttons is pressed;
• glutKeyboardFunc (myKeyboard)
which registers myKeyBoard () with the event that occurs when a
keyboard key is pressed. Conveniently, it is also passed data indicating
the location of the mouse at the time the key was pressed.
[1] Mouse Interaction
• You must design the callback function myMouse () to take four
parameters, so that it has the prototype
• void myMouse(int button, int state, int x, int y);
• Then, when a mouse event occurs, the system calls the registered
function, supplying it with values for these parameters.
• The value of button will be one of
GLUT_LEFT_BUTTON,
GLUT_MIDDLE_BUTTON, and
GLUT_RIGHT_BUTTON.
• The value of state will be one of GLUT_UP and GLUT_DOWN.
• The values x and y report the position of the mouse at the time of the
event.
(Be alert, however: The x value is the number of pixels from the left of the window,
as expected, but the y value is the number of pixels down from the top of the window!)
EXAMPLE 2.4.1 Placing dots with the mouse
• Each time the user presses down the left mouse button, a
dot is drawn in the screen window at the mouse position. If
the user presses the right button, the program terminates.
• The following version of myMouse () does the job.
void myMouse(int button, int state, int x, int y)
{
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
drawDot(x, screenHeight - y);
else
if(button == GLUT_RIGHT_BUTTON && state == GLUT__DOWN)
exit(-1);
}
EXAMPLE 2.4.2 Specifying a rectangle with the mouse
• Here, we want the user to be able to draw rectangles whose
dimensions are entered with the mouse. The user clicks the mouse
at two points that specify opposite corners of an aligned rectangle,
and the rectangle is drawn.
• Each new rectangle should replace the previous one.
• The user can clear the screen by pressing the right mouse button.
void myMouse(int button, int state, int x, int y)
static GLintPoint corner [2];
static int numCorners =0; // initial value is 0
if (button == GLUT_LEFT_BUTTON &&
state == GLUT_DOWN)
{
corner[numCorners].x = x;
corner[numCorners].y = y; // = screenHeight - y;
numCorners++; // have another point
if(numCorners == 2)
{
gIRecti(corner[0] .x, corner [0].y, corner[1].x, corner[1].y);
numCorners =0; // back to 0 corners
}
}
else
if(button == GLUT_RIGHT_BUTTON &&
state == GLUT_DOWN)
// clear the window
glClear(GL_COLOR_BUFFER_BIT);
gIFlush() ;
}
EXAMPLE 2.4.3 Controlling the Sierpinski gasket with the mouse
• It is simple to extend the Sierpinski gasket routine described earlier so that the user can
specify the three vertices of the initial triangle with the mouse. We use the same
process as in the previous example:
• Gather the three points in an array corners [], and when three points are
available, draw the Sierpinski gasket.
• The myMouse () routine is therefore as follows:
static GLintPoint corners [3] ;
static int numCorners = 0 ;
if(button == GLUT_LEFT_BUTTON &&
state == GLUT_DOWN)
corner[numCorners].x = x;
corner[numCorners].y = y ;
if(++numCorners == 3) Here, Sierpinski () is the same as in Figure 2.14,
{ except that the three vertices of the triangle are
Sierpinski(corners) ; passed as parameters.
numCorners = 0 ;
}
EXAMPLE 2.4.4 Create a polyline using the mouse
• The user enters a succession of points with the
mouse, and each point is stored in the next
available position of the array. If the array
becomes full, no further points are accepted,
• After each click of the mouse, the window is
cleared and the entire current polyline is
redrawn.
• The polyline is reset to empty if the right mouse
button is pressed
void myMouse(int button, int state, int x, int y)
{
#define NUM 20
static GLintPoint List[NUM];
static int last = -1;
// test for mouse button as well as for a full array
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && last <
(NUM -1))
{
List[++last].x = x; // add new point to list
List [ last].y = screenHeight - y;
glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_LINE_STRIP);
for(int i = 0; i <= last; i++)
glVertex2i(List [i].x, List[i].y);
glEnd();
gIFlush();
}
else if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
last = -1; // reset the list to empty
}
Mouse Motion
• An event of a different type is generated when the
mouse is moved (more than some minimal distance)
while some button is held down.
• The callback function
myMovedMouse ()
is registered with this event by using
glutMotionFunc(myMovedMouse);
• The callback function must take two parameters and
have the prototype void myMovedMouse (int x, int y);
• The values of x and y are, of course, the position of the
mouse when the event occurred.
EXAMPLE 2.4.5
"Freehand" drawing with a fat brush
• Suppose we want to create a curve by sweeping the mouse along some
trajectory with a button held down. In addition, we want it to seem that the
drawing "brush" has a square shape.
• This can be accomplished by designing myMovedMouse () to draw a
square at the current mouse position:
void myMovedMouse(int mouseX, int mouseY)
{
GLint x = mouseX;
GLint y = mouseY; // screenHeight – mouseY
GLint brushSize = 20;
//grab the mouse position
glRecti(x,y, x + brushSize, y + brushSize); gIFlush() ;
}
Do not forget to add
glutMotionFunc (myMovedMouse);
In function main
Keyboard Interaction
• As mentioned earlier, pressing a key on the keyboard
queues a keyboard event.
• The callback function myKeyboard() is registered with that
type of event through glutKeyboardFunc (myKeyboard)
• The function must have the prototype
void myKeyboard(unsigned int key, int x, int y);
• value of key is the ASCII value of the key pressed.
• The values x and y report the position of the mouse at the
time that the event occurred.
An example of the keyboard callback function
void myKeyboard(unsigned char theKey, int mouseX, int mouseY)
{
GLint x = mouseX;
GLint y = mouseY;
switch(theKey)
{
case 'p':
drawDot(x, y) ; // Draw dot at mouse position
break;
case GLUT_KEY_LEFT : List[++last].x = x;
List[ last].y = y;
break;
case 'E':
exit(-1) ; // terminate the program
default :
break;
}
}