Remembering the past to build the future

" Remembering the past to build the future "

Wednesday, 16 July 2014

Physics : Cloth with particles

This demo shows how you can use the Verlet Integration to build a cloth with particles. For understand the theory behind the code, visit the site

Müller-Fischer et al.
Real-time physics

And thanks to the material from the site


The demo project has the following structure:

The main class : phys_sim.cpp. In this class you will find 2 methods, the first one

void BuildCloth(int nbParticlesX, int nbParticlesY);

makes a cloth, while the second one

void BuildRope(int nbParticles);

makes a rope. Use the method:

void initGL(int width, int height) 
{
glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse_0);
glLightfv (GL_LIGHT0, GL_POSITION, light_positio_0);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

reshape(width, height);

glClearColor(0.126f, 0.126f, 0.128f, 1.0f);
glClearDepth(1.0f);

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

glShadeModel(GL_FLAT);
glEnable(GL_NORMALIZE);
//BuildRope(20);
BuildCloth(4,4);
}

for drawing a cloth or  a rope. The physics engine is realized through the following C++ sources:

constraint.h
particle.h
particle_system.h


Here it is a video demo:


Monday, 14 July 2014

Picking : Click and move an object

In this demo we have a cube in the scene. If you click on the cube, the cube changes its color to yellow:
the cube is now selected. Starting from a cube selected, a click on the plane moves the cube in the position where we have clicked. This video shows some examples:


The demo uses the unProject method as in the  Picking post . You will find in the code some modification for drawing the cube in a different position on the plane.

Download the source here:

C Sources

Wednesday, 2 July 2014

Object Picking

In this post I want to share an easy implementation of picking through unProject method. The demo is realized in C, so we have only the main.cpp file and vector3.h file. In the demo we have a cube in the center of the scene, when we click on the cube, the cube changes its color.




If you open the main.cpp source file you can note the following lines of code:

GLdouble posX, posY, posZ;
GLdouble cubeX=0,cubeY=0.5,cubeZ=0;
GLdouble cubeSize=1.f;
bool cubePicked;


The variables posX,posY and posZ give us the  unproject mouse click coordinates.
The variables cubeX,cubeY and cubeZ save the cube position.
The variable cubSize set the size of the cube;
The boolean variable cubePick is true when the cube is clicked;

When we click in the scene, the unProject method is called:

void unProject(){

GLint viewport[4]; // Where The Viewport Values Will Be Stored
glGetIntegerv(GL_VIEWPORT, viewport); // Retrieves The Viewport Values (X, Y, Width, Height)

GLdouble modelview[16]; // Where The 16 Doubles Of The Modelview Matrix Are To Be Stored
glGetDoublev(GL_MODELVIEW_MATRIX, modelview); // Retrieve The Modelview Matrix

GLdouble projection[16];  // Where The 16 Doubles Of The Projection Matrix Are To Be Stored
glGetDoublev(GL_PROJECTION_MATRIX, projection); // Retrieve The Projection Matrix

GLfloat winX, winY, winZ;               // Holds Our X, Y and Z Coordinates

winX = (float)mouse2D.x;                  // Holds The Mouse X Coordinate
winY = (float)mouse2D.y;                  // Holds The Mouse Y Coordinate

glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);

gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);

        //ROUND 2 DECIMAL
posX= ((int)(posX * 10 + .5) / 10.0);
posY= ((int)(posY * 10+ .5) / 10.0);
posZ= ((int)(posZ * 10 + .5) / 10.0);

}

the method saves posX,posY and posZ variables. After the pickingCheck method is called:

void pickingCheck(){

cubePicked=false;
if( posX>=cubeX-(cubeSize/2) && posX<=cubeX+(cubeSize/2)){
if( posY>=cubeY-(cubeSize/2) && posY<=cubeY+(cubeSize/2) ){
if( posZ>=cubeZ-(cubeSize/2) && posZ<=cubeZ+(cubeSize/2)){
cubePicked=true;
}
}
}

}

the method checks the posX,posY,posZ range values. If this values are inside the cube, the cube is picked.

Download the code from here:

Sources

Friday, 4 April 2014

Texture mapping on Torus

Hi, let's see a more complex texture mapping. In this demo I have written in the Geometry class a torus rendering method :

void torus(float out_radius, float int_radius, int textureId);

The method takes as input the tube radius ,the big radius from the center of the torus and a texture id. For a good quality rendering is important to set the normal on each vertex of the torus mesh, so for this reason we have the following private method used by torus:

Vector3 Geometry::getPointNormal(float out_angle,float int_angle, 
float out_radius,float int_radius){
 
 Vector3 tangentOut( -sin(out_angle), 
               cos(out_angle), 
      0);

 Vector3 tangentInt( cos(out_angle)*(-sin(int_angle)) ,
              sin(out_angle)*(-sin(int_angle)) ,
         cos(int_angle) );
 
 Vector3 normal = tangentOut^tangentInt;

 return normal.Normalize();

 }

getPointNormal() returns the normal vector (angles in radiants) for a vertex identified by polar coordinates. Another method used by the torus is:

Vector3 Geometry::getPoint(float out_angle,float int_angle, float out_radius,
float int_radius){

 return Vector3( ( out_radius+int_radius*cos(int_angle) )*cos(out_angle),
                 ( out_radius+int_radius*cos(int_angle) )*sin(out_angle),
                                         int_radius*sin(int_angle));
  
}

That returns cartesian coordinates from polar coordinates. For apply the texture we have the method:

void Geometry::glTorusTexCoord(float out_angle,float int_angle,int tx){

 glTexCoord2f( out_angle/PI , (int_angle)/PI );
 
}
The texture file must reside in your project directory. In my case I made a directory called texture and I put the file here.

Download the sources here


Here it is the video demo:



Thursday, 3 April 2014

OpenGL Texture Mapping

In this post I decided to get some Quake texture and making a simple but interesting 3D scene. As the other OpenGL post, we have a project with some C++ files and classes like Geometry,Scene,Main but in this demo I have used an external class for texture loading, TextureLoader inside the project. The first thing you have to control before to worry about compilation error is the following setting in your Visual C++ project:




Check Character Set = Not Set. Let's see the video demo before to start:




You can download the code here:

Texture Demo

For texture loader you can find all documentation here:

http://members.iinet.net.au/~cleathley/openGL/TextureLoader.htm

If you open the Scene class you can find the following fragment code on the top:

TextureLoader* Scene::pTextureLoader=new TextureLoader();
glTexture    Scene::floor;
glTexture    Scene::box;
glTexture    Scene::box2; 
TextureLoader is the class that loads the textures. We have three different textures, one for floor and two for boxes. The initGL() method inside the Scene class has now the code to initialize the textures:
 pTextureLoader->LoadTextureFromDisk("\\texture\\floor.jpg", &Scene::floor);
 pTextureLoader->LoadTextureFromDisk("\\texture\\box.jpg", &Scene::box); 
 pTextureLoader->LoadTextureFromDisk("\\texture\\box2.jpg", &Scene::box2); 
The texture files must reside in your project directory. In my case I made a directory called texture and I put all files here. With Geometry class in the draw() method of the Scene class, we find the code to draw all boxes using textures:
Geometry geo;

   glPushMatrix();
 glTranslatef(-3,0.75,5);
 geo.box(1.5f,1.5f,1.5f,Scene::box.TextureID);
   glPopMatrix();

   glPushMatrix();
 glTranslatef(-3,0.75,2);
 geo.box(1.5f,1.5f,1.5f,Scene::box.TextureID);
   glPopMatrix();
 
   glPushMatrix();
 glTranslatef(-3,0.75,-1);
 geo.box(1.5f,1.5f,1.5f,Scene::box.TextureID);
    glPopMatrix();

    glPushMatrix();
 glTranslatef(-3,0.75,-4);
 geo.box(1.5f,1.5f,1.5f,Scene::box.TextureID);
    glPopMatrix();

 
    glPushMatrix();
 glTranslatef(3,0.75,5);
 geo.box(1.5f,1.5f,1.5f,Scene::box2.TextureID);
    glPopMatrix();

    glPushMatrix();
 glTranslatef(3,0.75,2);
 geo.box(1.5f,1.5f,1.5f,Scene::box2.TextureID);
    glPopMatrix();
 
    glPushMatrix();
 glTranslatef(3,0.75,-1);
 geo.box(1.5f,1.5f,1.5f,Scene::box2.TextureID);
    glPopMatrix();

    glPushMatrix();
 glTranslatef(3,0.75,-4);
 geo.box(1.5f,1.5f,1.5f,Scene::box2.TextureID);
    glPopMatrix();

If you want to see how textures have been applied to boxes see the box method of the class Geometry:
void Geometry::box(GLdouble width, GLdouble height, GLdouble lenght,int textureId){
  
    glEnable(GL_TEXTURE_2D); 
    glShadeModel(GL_FLAT);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_MODULATE);

    glBindTexture(GL_TEXTURE_2D, textureId);

    // Front
   glBegin(GL_QUADS);
      glNormal3d(0, 0, lenght/2);
      glTexCoord2f(0, 0);
      glVertex3d(-width/2, height/2, lenght/2);
      glTexCoord2f(1, 0);
      glVertex3d(width/2, height/2, lenght/2);
      glTexCoord2f(1, 1);
      glVertex3d(width/2, -height/2, lenght/2); 
      glTexCoord2f(0, 1);
      glVertex3d(-width/2, -height/2, lenght/2);
   glEnd();

    // Right
   glBegin(GL_QUADS);
      glNormal3d(-width/2, 0, 0);
      glTexCoord2f(0, 0);
      glVertex3d(-width/2, +height/2, -lenght/2);
      glTexCoord2f(1, 0);
      glVertex3d(-width/2, +height/2, lenght/2);
      glTexCoord2f(1, 1);
      glVertex3d(-width/2, -height/2, lenght/2);
      glTexCoord2f(0, 1);
      glVertex3d(-width/2, -height/2, -lenght/2);
    glEnd();

    // Back
    glBegin(GL_QUADS);
       glNormal3d(0, 0, -lenght/2);
       glTexCoord2f(0, 0); 
       glVertex3d(width/2, height/2, -lenght/2);
       glTexCoord2f(1, 0);
       glVertex3d(-width/2, height/2, -lenght/2);
       glTexCoord2f(1, 1);
       glVertex3d(-width/2, -height/2, -lenght/2);
       glTexCoord2f(0, 1);
       glVertex3d(width/2, -height/2, -lenght/2);
    glEnd();

     // Left
    glBegin(GL_QUADS);
       glNormal3d(width/2, 0, 0);
       glTexCoord2f(0, 0);
       glVertex3d(width/2, height/2, lenght/2);
       glTexCoord2f(1, 0);
       glVertex3d(width/2, height/2, -lenght/2);
       glTexCoord2f(1, 1);
       glVertex3d(width/2, -height/2, -lenght/2);
       glTexCoord2f(0, 1);
       glVertex3d(width/2, -height/2, lenght/2);
     glEnd();

     // Top
     glBegin(GL_QUADS);
       glNormal3d(0, height/2, 0);
       glTexCoord2f(0, 0);
       glVertex3d(-width/2, height/2, -lenght/2);
       glTexCoord2f(1, 0);
       glVertex3d(width/2, height/2, -lenght/2);
       glTexCoord2f(1, 1);
       glVertex3d(width/2, height/2, lenght/2);
       glTexCoord2f(0, 1);
       glVertex3d(-width/2, height/2, lenght/2);
     glEnd();

     // Bottom
     glBegin(GL_QUADS);
        glNormal3d(0, -height/2, 0);
        glTexCoord2f(0, 0);
        glVertex3d(-width/2, -height/2, lenght/2);
        glTexCoord2f(1, 0);
        glVertex3d(width/2, -height/2, lenght/2);
        glTexCoord2f(1, 1);
        glVertex3d(width/2, -height/2, -lenght/2);
        glTexCoord2f(0, 1);
        glVertex3d(-width/2, -height/2, -lenght/2);
     glEnd();

     glDisable(GL_TEXTURE_2D);
}

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