Find REAL3D on facebook

OpenGL Tutorial - 3

Render a Triangular Model in OpenGL? or how to use glBegin(GL_TRIANGLES) in OpenGL? or How to use "for loop" for rendering a big triangular model? or How to make a data structure for 3D model rendering? or How to use a header file?

In this tutorial you are going to learn

  • How to render a triangle?
  • How to render a triangular model?
  • How to use "for loop" for rendering a big triangular model?
  • How to make a data structure for 3D model rendering? (very important)
  • How to declare a array pointer?
  • How to use declared pointers for rendering 3D model?
  • How to make a header file?
  • How to use a header file?
  • How to make a function with local variables?

  • I am assuming that you have successfully compiled your first and second program using my OpenGLTest_Animation.cpp file or using my Visual Studio project. In this tutorial, we are going to use a header file for data structure and short math algorithms. Data structure is very important in 3D graphics programming, if you have a proper data structure, only then you can extend your application or software further for new ideas and algorithms. But if you were made a data structure improper, improper means that will not be perfect for many algorithms, then you can't use your data structure with those algorithms. You can convert their (Google) algorithms same as your data structure demands, but it will take so much time, and it's very complicated, sometime you give up and through away. I had the same problem when I was working on my softwares, then I realized that what if I had made a perfect data structure before, and now I could save my so much time which I have wasted on just data structure conversion.

    Anyways, let's start to make a new header file. In order to create a new header file, just follow the steps which we have done for creating a *.cpp file in the first tutorial. In this header file, we are going to make a data structure for the triangular model. Here we will render a triangular cube which will be composed of 8 vertices and 12 indices. By creating two structures one for vertices and second for indices of the model, we create some pointers to those structures, and we allocate arrays memory to 12 and 8 for triangles and vertices, respectively.

    The header file for rendering a triangular model can be downloaded from here. The file contains data structure, some pointers to sturcture, and veriables, etc.

    File Name Type Size Release Date
    myMath *.h 1.09 KB 2012.06.23

    	Created:	2012/06/23
    	Created:	23:6:2012   2:48
    	Filename: 	myMath.h
    	Author:		Furqan Ullah
    	Disclaimer:	This tutorial has been written for learning purposes only.
    #ifndef __myMath_H__
    #define __myMath_H__
    #include < math.h>
    struct GLpoint // A Structure To Hold Point Data of triangles
    	GLfloat x, y, z; // The Components Of The GLpoint
    struct GLFace // A Structure To Hold Face Data of triangles
    	unsigned int v1, v2, v3; // The Components Of The GLFace
    GLpoint p_VERTICES[8]; // pointer to vertices of the main model
    GLpoint FaceNormals[12]; // pointer to face normals (triangle normal) of the main model 
    int	nb_Vertices = 0; // number of total vertices of main model
    GLFace p_indices[12]; // pointer to indices (vertex index) of the main model
    int	nb_Faces = 0; // number of total triangles of main model

    Now come back to *.cpp file, firstly we need to make a data (triangles positions and indices) for a cube. For this purpose, I made a function name getTriangularModelData(), by using this function we will have triangles positions and indices information in our data structure. After then we will use our data structure to render a triangular model using this function Draw_TriangularModel( , , , ). It's really simple and easy, I have created all information that anyone needs for rendering a triangular model in this tutorial. You can use my header and *.cpp files and render your 3D model.

    Note: I am not including normals in this tutorial, because for rendering normals, we also need to know about 3D lights of OpenGL, first I will describe about lights in the next tutorial and then I will include normals rendering. In this tutorial, you will find a wireframe rendering of a cube.

    In the *.cpp file, You will also find one function name Draw_One_Triangle(void). I just wanted to make your concept clear by including this function. You will find that how can we apply colors to triangles of a 3D model.

    If you have successfully done your previous tutorial, then it will be very easy to understand this tutorial. Just follow the code. I didn't change anything in the *.cpp file of the previous tutorials, I just added some functions, use them wherever you want.

    Note: Actually, whenever we use pointers it means you are allocating some memory, but you should know between static and dynamic memory. When you will study about it then you will know that we do not need to de-allocate the arrays memory, array will automatically be de-allocated whenever you exit your application. The system will release all the allocated memory by your application just after your press exit. But in case of dynamic memory, de-allocation of memory is very important, there must not be any kind of leak in your application or software, otherwise you will find some bugs, instability in your software, etc. In our case, in this tutorial we only allocated the arrays memory, so we don't need any kind of de-allocation.

    The code and *.cpp file for the 3rd tutorial can be found below.

    File Name Type Size Release Date
    OpenGLTest_Rendering_A_Triangular_Model *.cpp 9.73 KB 2012.06.23

    	Created:	2012/06/23
    	Created:	23:6:2012   2:48
    	Filename: 	OpenGLTest_Rendering_A_Triangular_Model.cpp
    	Author:		Furqan Ullah
    	Disclaimer:	This tutorial has been written for learning purposes only.
    #include "myMath.h"  // declaration of header file
    /*  I made this data set myself for rendering a Cube. A Cube contains 8 vertices and 12 triangles. */
    /*  You can change size of the cube by changing xsize, ysize, zsize variables. */
    void getTriangularModelData()
    	float xsize = 20.0; float ysize = 20.0; float zsize = 20.0;
    	// cube vertices positions in x, y, z
    	p_VERTICES[0].x =  xsize; p_VERTICES[0].y =  ysize; p_VERTICES[0].z = -zsize; // position of 1st vertex (x, y, z)
    	p_VERTICES[1].x =  xsize; p_VERTICES[1].y =  ysize; p_VERTICES[1].z =  zsize; // position of 2nd vertex (x, y, z)
    	p_VERTICES[2].x =  xsize; p_VERTICES[2].y = -ysize; p_VERTICES[2].z = -zsize; // position of 3rd vertex (x, y, z)
    	p_VERTICES[3].x =  xsize; p_VERTICES[3].y = -ysize; p_VERTICES[3].z =  zsize; // position of 4th vertex (x, y, z)
    	p_VERTICES[4].x = -xsize; p_VERTICES[4].y = -ysize; p_VERTICES[4].z = -zsize; // position of 5th vertex (x, y, z)
    	p_VERTICES[5].x = -xsize; p_VERTICES[5].y = -ysize; p_VERTICES[5].z =  zsize; // position of 6th vertex (x, y, z)
    	p_VERTICES[6].x = -xsize; p_VERTICES[6].y =  ysize; p_VERTICES[6].z = -zsize; // position of 7th vertex (x, y, z)
    	p_VERTICES[7].x = -xsize; p_VERTICES[7].y =  ysize; p_VERTICES[7].z =  zsize; // position of 8th vertex (x, y, z)
    	nb_Vertices = 8; // total number of vertices
    	// cube indices
    	p_indices[0].v1 = 0; p_indices[0].v2 = 1; p_indices[0].v3 = 2; // 1st triangle
    	p_indices[1].v1 = 3; p_indices[1].v2 = 2; p_indices[1].v3 = 1; // 2nd triangle
    	p_indices[2].v1 = 2; p_indices[2].v2 = 3; p_indices[2].v3 = 4; // 3rd triangle
    	p_indices[3].v1 = 5; p_indices[3].v2 = 4; p_indices[3].v3 = 3; // and so on
    	p_indices[4].v1 = 4; p_indices[4].v2 = 5; p_indices[4].v3 = 6;
    	p_indices[5].v1 = 7; p_indices[5].v2 = 6; p_indices[5].v3 = 5;
    	p_indices[6].v1 = 6; p_indices[6].v2 = 7; p_indices[6].v3 = 0;
    	p_indices[7].v1 = 1; p_indices[7].v2 = 0; p_indices[7].v3 = 7;
    	p_indices[8].v1 = 0; p_indices[8].v2 = 2; p_indices[8].v3 = 4;
    	p_indices[9].v1 = 4; p_indices[9].v2 = 6; p_indices[9].v3 = 0;
    	p_indices[10].v1 = 1; p_indices[10].v2 = 5; p_indices[10].v3 = 3;
    	p_indices[11].v1 = 5; p_indices[11].v2 = 1; p_indices[11].v3 = 7;
    	nb_Faces = 12; // total number of indices
    /* This function will render only one triangle with 3 colors of each side.*/
    void Draw_One_Triangle(void)
    		glColor3f(1.0, 0, 0); // apply color on 1st vertex
    		glVertex3f(0, 0, 0);
    		glColor3f(0.0, 1.0, 0); // apply color on 2nd vertex
    		glVertex3f(15, 0, 0);
    		glColor3f(0.0, 0, 1.0); // apply color on 3rd vertex
    		glVertex3f(15, 15, 0);
    /* This function will render a triangular model. You will realize that here I am using float pointer for rendering vertices of triangle.*/
    /* This is optimized and efficient way, do use it.*/
    /* GLpoint *P is a pointer to vertices of model */
    /* GLpoint *Fn is a pointer to face normals of model (face normal means normal vector of a triangle)*/
    /* GLFace *T is a pointer to indices of model. Indices means triangles corners i.e., v1, v2, v3 */
    /* int nbF = total number of triangles of model */
    void Draw_TriangularModel(GLpoint *P, GLpoint *Fn, GLFace *T, int nbF)
    	for (int i=0; i < nbF; i++)
    		//glNormal3fv((float *)&Fn[i]); we are not using face normals in this tutorial	
    		glVertex3fv((float *)&P[T[i].v1]);
    		glVertex3fv((float *)&P[T[i].v2]);	
    		glVertex3fv((float *)&P[T[i].v3]);
    /* This is the main OpenGL function. Whatever you want to draw in your OpenGL application, you will need to write in this function only. */
    /* This is a real-time activated function, this function operates like a loop function,  */
    void display(void)
    	glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // you can apply background color by setting RBG values here.
    		glRotatef(15.0, 1.0, 0.0, 0.0);
    		glRotatef(30.0, 0.0, 1.0, 0.0);
    		glRotatef(0, 0.0, 0.0, 1.0);
    		glutIdleFunc(ModelRotation); // Idle function of OpenGL, idle function means it will never stop until the application is terminated or your stop by your self.
    		glRotatef(Rot_Cangle_animate, 1.0f, 0.0f, 0.0f); // apply rotation around X-axis
    		glRotatef(Rot_Cangle_animate, 0.0f, 0.0f, 1.0f); // rotation around Z-axis
    		//glutWireCube(30.0); // render a wire cube with size 30
    		//glutWireTeapot(15.0); // if you want to render a teapot, just uncomment it.
    		//glutWireTorus(5.0, 20.0, 20.0, 20.0); // how about to render a torus, have fun 
    		Draw_One_Triangle(); // rendering a triangle
    		glColor3f(1.0f, 1.0f, 1.0f); // apply color to object (Cube)
    		Draw_TriangularModel(p_VERTICES, FaceNormals, p_indices, nb_Faces); // rendering a triangular model

    opengltest.cpp Output

    Output result of OpenGLTest_Rendering_A_Triangular_Model.cpp file.

    You have learned your third lesson. Now you are able to render any 3D model exported from SolidWorks, ProE, etc. Try it. Good Luck.