OpenGL Programming/Basics/2DObjects

Drawing Triangles and Quads

edit

glRectf(), while useful, doesn't allow us very much control over the individual vertices of our rectangle. To give us more control, and the ability to draw more complicated shapes, we have to use different functions.

Stand-Alone Vertex-Defined Shapes

edit

Starting a Vertex-Defined Shape

edit

To start a shape defined by vertices, we use the glBegin() function. glBegin takes one argument: the type of shape you want to make. Here are some possible arguments:

  • GL_TRIANGLES
  • GL_QUADS
  • GL_POLYGON

A quad is any shape with 4 vertices: a rectangle, a square, a trapezoid, etc. The position of the vertices will define what type of shape it is.

While polygon sounds ideal for drawing complicated shapes, scroll down for a warning on the limitations of polygons: there are quite a few, and you might be better off using a series of connected quads or triangles in certain cases.

Defining Vertices

edit

After you have called glBegin, we actually define the vertices using glVertex2f(float xPosition, float yPosition):

glBegin(GL_XYZ);
glVertex2f(-1.0f,-0.5f);
glVertex2f(1.0f,-0.25f);
...

Important Note: The order in which you define vertices is important! In general, if you define the vertices in counter-clockwise order, the front face will be facing towards you, which is usually what you want. The distinction becomes very important once we go into 3D, so make sure to define your vertices counter-clockwise unless you know what you're doing! If you would prefer to define your vertices in clockwise order, make sure to include this function in your setup() function:

glFrontFace(GL_CW);

which will allow you to draw only in clockwise order.

Finishing Up

edit

To end a vertex-defined shape, simply call glEnd(), which takes no arguments.

Example

edit

This display function will draw a black trapezoid centered in our screen.

void display() {
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       glColor3f(0.0f, 0.0f, 0.0f); // sets color to black.
       glBegin(GL_QUADS);
               glVertex2f(-0.25f, 0.25f); // vertex 1
               glVertex2f(-0.5f, -0.25f); // vertex 2
               glVertex2f(0.5f, -0.25f); // vertex 3
               glVertex2f(0.25f, 0.25f); // vertex 4
       glEnd();
       glutSwapBuffers();
}

Note on Style: Calls to glVertex() are sometimes indented to separate them from the glBegin and glEnd. The indentation in the previous example was not a mistake.

Drawing a Series of Connected Shapes Efficiently

edit

If we're going to draw a series of shape where every one shares an edge or vertex with the other, there's no reason to repeat so many calls to glVertex2f(). Instead, we call glBegin with a special argument to signal that we want a "strip" of these objects.

Using glBegin with GL_TRIANGLE_STRIP or GL_QUAD_STRIP

edit

When we call glBegin with either of these two arguments, we can draw a series of triangles or quads, each of which shares one edge with another triangle or quad. One good use for this is drawing complicated shapes, e.g. a 2D Christmas tree.

A triangle strip is defined by 3 initial vertices for the triangle, and then one vertex for each additional triangle. Any given triangle is formed by its one vertex and the two vertices immediately before.

A quad strip is defined by 4 initial vertices for the quad, and then two vertices for each additional quad. Any given quad is formed by its two vertices and the two vertices that come immediately before.

Example

edit
 
Sample output of this program

The following code defines a house shape, with a slanted roof, using triangle strips:

void display() {
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       glColor3f(0.0f, 0.0f, 0.0f); // sets color to black.
       glBegin(GL_TRIANGLE_STRIP); // draw in triangle strips
               glVertex2f(0.0f, 0.75f); // top of the roof
               glVertex2f(-0.5f, 0.25f); // left corner of the roof
               glVertex2f(0.5f, 0.25f); // right corner of the roof
               glVertex2f(-0.5f, -0.5f); // bottom left corner of the house
               glVertex2f(0.5f, -0.5f); //bottom right corner of the house
       glEnd();
       glutSwapBuffers();
}

Here, three triangles are defined, one for the roof, one for the upper left corner of the house, and one for the lower right corner of the house.

Using glBegin with GL_TRIANGLE_FAN

edit

If we want to draw a bunch triangles where every triangle shares a predefined vertex (for example, at the origin), we can use a triangle fan. Triangle fans define a shape through an odd number of vertices. The first vertex defines a center point which every triangle will have as a vertex. Every two vertices are then used with the initial vertex to define a triangle.

#include <GL/glut.h>

void init(){ 
    glClearColor(0,0,0,0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0,100,0,200);
}
void Display(){
     glClear(GL_COLOR_BUFFER_BIT);
     glBegin(GL_TRIANGLE_FAN);
         glColor3f(1,0,0);
         glVertex2f(0,0.5);
         glVertex2f(-0.4,0);
 	 glVertex2f(0.4,0);
         glColor3f(0,1,0);
 	 glVertex2f(0,-0.5);
     glEnd();
     glFlush(); 
} 

int main(int argc, char **argv){ 	
    glutInit(& argc, argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(200,200);
    glutCreateWindow("line");
    glutDisplayFunc(Display);
    init();
    glutMainLoop();
	
    return 0;
}

Shapes Built In to GLUT

edit

GLUT has a few built-in objects that can be used just by calling a simple function. The most interesting and useful of these are:

Function 2D Shape 3D Shape Comments
glutSolidSphere(float radius, int slices, int stacks) Circle Sphere Choose an integer 20-100 for the slices and stacks arguments; the higher the number, the more accurate the sphere/circle.
glutSolidCube(double size) Square Cube
glutSolidCone(double base, double height, int slices, int stacks) Triangle Cone The greater the slices argument is, the smoother the cone will appear.
glutSolidTorus(double innerRadius, double outerRadius, int nSides, int rings) Torus
glutSolidTeapot(float radius) Teapot Teapot Yes, a teapot. See the Wikipedia article "Utah Teapot" to find out why a teapot was chosen.