Remembering the past to build the future

" Remembering the past to build the future "

Saturday 29 March 2014

OpenGL Hierarchical Models

In many applications the parts of a model depend on one another: if we move one part, it causes other parts to move. We represent such models using trasformations. OpenGL trasformations are applied to the existing model-view matrix. Each trasformation represents a relative change from one scaling,position and orientation to another. In this post I show you a demo with a lamp. You can move some parts of the lamp using the keys 'a','s','d','f','g','h' from your keyboard. The lamp uses also a diffuse light with an emissive component. Here it is the video demo:




You can download the code here:
The demo uses the template code showed in the previous post plus other useful methods.
Inside the code you can find the drawLamp() methods with the following code:
 Geometry geo;
 int colors1[]={0,127,255, 102,255,0};
 int colors2[]={    255,153,51, 255,153,51, 255,153,51, 
        255,153,51, 255,153,51, 255,153,51};
 glPushMatrix();
 float   HEIGHT_CYL_A  = 0.5f;//BASE  HEIGHT
 float   HEIGHT_CYL_B  = 1.5f;//MIDDLE  HEIGHT
 float   HEIGHT_CYL_C  = 0.5f;//TOP  HEIGHT
 float   SPHERE_RADIUS = 0.5f;//SPHERE RADIUS
 /* Draw Base Start */
 glRotatef(arm1Angle,0,1,0);
 glTranslatef(0,HEIGHT_CYL_A/2,0);
 geo.box(2,HEIGHT_CYL_A,2,colors2);
 /* Draw Base End */
 /* Draw Sphere Joint Start*/
  glTranslatef(0,SPHERE_RADIUS/2+HEIGHT_CYL_A,0);
  geo.sphere(SPHERE_RADIUS,10,10,colors1);
 /* Draw Sphere Joint End*/
 /* Draw first middle Arm Start */
 glRotatef(-20,0,0,1);
 glTranslatef(0,SPHERE_RADIUS+HEIGHT_CYL_B/2,0);
 geo.box(1,HEIGHT_CYL_B,1,colors2);
 /* Draw first middle Arm End */
 /* Draw Sphere Joint Start*/
  glTranslatef(0,SPHERE_RADIUS+HEIGHT_CYL_B/2,0);
  geo.sphere(SPHERE_RADIUS,10,10,colors1);
 /* Draw Sphere Joint End*/
 /* Draw second middle Arm Start */
 glRotatef(arm2Angle,0,0,1);
 glTranslatef(0,SPHERE_RADIUS+HEIGHT_CYL_B/2,0);
 geo.box(1,HEIGHT_CYL_B,1,colors2);
  /* Draw second middle Arm End */
  /* Draw Sphere Joint Start*/
  glTranslatef(0,SPHERE_RADIUS+HEIGHT_CYL_B/2,0);
  geo.sphere(SPHERE_RADIUS,10,10,colors1);
 /* Draw Sphere Joint End*/
   /* Draw third Arm Start */
 glRotatef(arm3Angle,0,0,1);
 glTranslatef(0,SPHERE_RADIUS+HEIGHT_CYL_C/2,0);
 geo.box(2,HEIGHT_CYL_C,2,colors2);
  /* Draw third  Arm End */
 /*Sphere emission*/
 GLfloat mat_emission[] = {0.5, 0.8, 0.9, 0.0};
 glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
 /* Draw Sphere Final  Start*/
  glTranslatef(0,SPHERE_RADIUS+HEIGHT_CYL_C/2,0);
  geo.sphere(SPHERE_RADIUS,10,10,colors1);
  glEnable(GL_LIGHT1);
 /* Draw Sphere Final End*/
  
  /*Put light near the final sphere*/
  glEnable(GL_LIGHT1);
  GLfloat pos[]={ 0.0, 0.0, 0.0, 1.0};
  GLfloat color[]={ 1.0, 1.0, 1.0, 1.0};
  //glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0);// set cutoff angle
  glLightfv(GL_LIGHT1, GL_POSITION, pos); 
  glLightfv(GL_LIGHT1, GL_DIFFUSE, color);
  //glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2);
  GLfloat mat_emission2[] = {0, 0, 0, 0.0};
  glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission2);
  glPopMatrix();
In this code you can see how every part of the lamp is realized starting from the previous part. And this is an alternative demo:



OpenGL Transformations

In this post I want to show 3D affine trasformations using OpenGL functions like glTranslate(), glRotate() ,glPushMatrix and glPopMatrix(). Here the final result:






You can download the c++ sources from the url: OpenGL Demo Use left mouse button to rotate the scene and middle plus right button for zoom. In the sources you will find some classes:
  • Geometry class allows you  boxes and spheres rendering with different colors
  • Scene class allows you to make a complete scene using Geometry
  • Main class starts the application
You can use Visual C++ Express Edition to build the demo but it's important to have OpenGL well configured in your environment, you can use this url to see how configure OpenGL: OpenGL configuration
Now open the sources and the Scene class. In this class we have several methods, for now we want to focus on draw() method. This method draws the scene and here we find the OpenGL code trasformations:

Geometry geo;

 int colors1[]={ 255,153,51, 0,127,255, 255,153,51, 
        0,127,255, 0,127,255, 0,127,255};
 
 int colors2[]={ 0,127,255, 102,255,0};
 int colors3[]={ 255,0,0, 255,0,0, 255,0,0, 
        255,0,0, 255,0,0, 255,0,0};
 
 int colors4[]={ 0,255,0, 0,255,0};
 int colors5[]={ 255,255,0, 255,255,0};
 
 /*Sphere in (0,1,0) 90 degree rotated around x axes
   Note:First trasformation is the rotation
        Second trasformation is the translation
        So you have to read the trasformations 
        from down to up in your code
  */
 glPushMatrix();
  glTranslatef(0,1,0);//Second
  glRotatef(90,1,0,0);//First
  geo.sphere(1,20,20,colors2);
 glPopMatrix();

 /*Box in (2,0.75,2)*/
 glPushMatrix();
  glTranslatef(2,0.75,2);
  geo.box(1.5,1.5,1.5,colors1);
 glPopMatrix();

 /*Box in (-2,0.75,-2)*/
 glPushMatrix();
  glTranslatef(-2,0.75,-2);
  geo.box(1.5,1.5,1.5,colors3);
 glPopMatrix();

 /*Sphere in (3,1,-3)  90 degree rotated around x axes*/
 glPushMatrix();
  glTranslatef(3,1,-3);
  glRotatef(90,1,0,0);
  geo.sphere(1,20,20,colors4);
 glPopMatrix();
 
 /*Sphere in (-4,1,4)  90 degree rotated around x axes*/
 glPushMatrix();
  glTranslatef(-4,1,4);
  glRotatef(90,1,0,0);
  geo.sphere(1,20,20,colors5);
 glPopMatrix();

 /* */
The glPushMatrix() save the current ModelView matrix, the glPopMatrix() restore the matrix saved. So we have used this methods to save current trasformation matrix before to apply our trasformations for a box or a sphere and then restore the initial trasformation matrix. If you note the code for a sphere, you can see a trasformation composition. The sphere is first rotated and then translated. Use this fragment code to play with trasformations and understand how OpenGL works with them.Well I have finished for now. I hope this post is useful.
Thanks for reading.

My Android Games, much are free