Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links

Objetos básicos en OpenGL

Esta escena esta compuesta por tres objetos basicos, una esfera, un cubo y un toro. Ademas por una grilla formada por lineas, una fuente de luz puntual, y tres materiales. En este caso utilice los objetos definidos en la libreria GLUT.

Los Objetos

El cubo

Su sintaxis es:

void glutSolidCube(GLdouble size), donde size, es la longitud de uno de sus lados, en este caso size=2.0 y lo situo en el punto (1.0,1.0,1.0), con la funcion glTranslatef (1.0, 1.0, 1.0), con un angulo de rotacion alrededor del eje Y de 15 grados glRotatef(15.0, 0.0, 1.0, 0.0).

Expecificacion del material (Azul):

GLfloat mat_ambient_cubo[] = {0.1, 0.1, 0.1, 1.0f}; 
GLfloat mat_diffuse_cubo[] = {0.0, 0.0, 0.8, 1.0f};
GLfloat mat_specular_cubo[] = {0.9, 0.9, 0.9, 1.0f};
glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient_cubo);
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse_cubo);
glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular_cubo);
glMaterialf (GL_FRONT, GL_SHININESS, 100.0f);

La esfera

Sintaxis : void glutSolidSphere(GLdouble radius,GLint slices, GLint stacks), radius = radio de la esfera, slice = numero de subdiviciones alrededor del eje Z, staks = numero de subdivisiones a lo largo del eje Z, en nuestra escena la esfera es glutSolidSphere (1.0, 16, 16) y situada en (-1.0,1.0, 0.0) con respecto al origen glTranslatef (-1.0, 1.0, 0.0).

Su material (Verde) :

GLfloat mat_ambient_esfera[] = {0.1, 0.1, 0.1, 1.0f}
GLfloat mat_diffuse_esfera[] = {0.0, 0.7, 0.0, 1.0f}
GLfloat mat_specular_esfera[] = {0.8, 0.8, 0.8, 1.0f}
glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient_esfera)
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse_esfera)
glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular_esfera)
glMaterialf (GL_FRONT, GL_SHININESS, 100.0f)

El toro

Sintaxis: void glutSolidTorus(GLdouble innerRadius,GLdouble outerRadius,GLint nsides, GLint rings),innerRadius=radio menor, outerRadius=radio mayor, nsides=numero de caras para cada una de las secciones radiales, rings=numero de secciones radiales, su ubicacion:

glTranslatef (-2.0, 1.0, 2.0)
glRotatef(-45.0, 0.0, 1.0, 0.0)
glRotatef(-45.0, 1.0, 0.0, 0.0)

Su material (color Rojo) :

GLfloat mat_ambient_toro[] = {0.05, 0.05, 0.05, 1.0f} 
GLfloat mat_diffuse_toro[] = { 0.8, 0.0, 0.0, 1.0f}
GLfloat mat_specular_toro[] = {0.9, 0.8, 0.8, 1.0f}
glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient_toro)
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse_toro)
glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular_toro)
glMaterialf (GL_FRONT, GL_SHININESS, 50.0f)

La fuente de luz

La función parece igual a la de los materiales pero cuidado que no lo es.

Característica ambiental: GLvoid glLightfv ( GLenum light, GL_AMBIENT, const GLfloat *params ).

Define la contribución de esta fuente de luz a la luz ambiental de la escena. Por defecto la contribución es nula.

Característica difusa: GLvoid glLightfv ( GLenum light, GL_DIFFUSE, const GLfloat *params ).

La componente difusa de la fuente es lo que entendemos como el color que tiene la luz. Para GL_LIGHT0 los valores RGBA por defecto valen 1.0. Para el resto de luces los valores por defecto son 0.0.

Característica especular GLvoid glLightfv ( GLenum light, GL_SPECULAR, const GLfloat *params )

Se trata de la luz que viene de una dirección particular y rebota sobre un objeto siguiendo una determinada dirección. Es la componente responsable de las zonas más brillantes en la geometría, de los "highlights". Para conseguir un efecto suficientemente realista deberíamos dar a este parámetro el mismo valor que a la componente difusa. Al igual que en el caso anterior, en la primera luz los valores RGBA valen 1.0 mientras que en el resto 0.0.

Tenemos que especificar dónde queremos colocar cada una de las fuentes de luz. Para ello utilizamos la función de siempre: GLvoid glLightfv ( GLenum light, GL_POSITION, const GLfloat *params ).

Notar el úso de la constante GL_POSITION.En este caso *params se corresponde con el valor de la coordenada homogénea (X, Y, Z, W) dónde colocar la luz. Si w = 0.0 se considerará que la luz se encuentra infinitamente lejos de nosotros. En ese caso su dirección se deduce del vector que pasa por el orígen y por el punto (X, Y, Z). Si w = 1.0 se considera su posición con toda normalidad.

Por defecto la luz se encuentra en (0.0, 0.0, 1.0, 0.0) iluminando en la dirección negativa del eje Z.

Los rayos de la luz se asumen paralelos.

Podemos mover una luz a gusto por una escena. Incluso podemos movernos con ella como si fuera una linterna. Para ello tan sólo tenemos que considerarla como un objeto 3D más que se ve afectado por cambios en la matriz de transformación "MODEL-VIEW" de OpenGL. Podemos rotarla, trasladarla, escalar su posición....como si de un polígono se tratara.

En nuestra escena tenemos definidas las siguientes caracteristicas para la fuente de luz:

GLfloat light_ambient[] = { 0.75, 0.75, 0.75, 1.0 }
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }
GLfloat light_position[] = { 0.0, 0.0, 1.0, 0.0 }
glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient)
glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse)
glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular)
glLightfv (GL_LIGHT0, GL_POSITION, light_position)

La Grilla

Es simplemente un conjunto de lineas que se extienden desde -10.0, a 10.0 con un paso de 1.0 unidades, en el plano X,Z.

Su material, es simplemente un color plano definido glColor3f( 0.0, 0.7, 0.7 ) , la fuente de luz es desactivada para hacer el render de la grilla.

Ejemplo de una escena iluminada con una luz puntual

Código Fuente


/*
 escena.c
 Este programa muestra como definir un fuente de luz y
 el dibujo de algunas primitivas con sus respectivos materiales
 Ramiro Alcocer
 valcoey@hotmail.com
 www.oocities.org/valcoey/index.html
*/

#include <stdlib.h>
#include <GL/glut.h>

GLfloat elevacion =   0.0f;
GLfloat azimitud  =   0.0f;
GLfloat giro      =   0.0f;

//parametros para construir la grilla
#define DEF_floorGridScale	1.0
#define DEF_floorGridXSteps	10.0
#define DEF_floorGridZSteps	10.0

void polarView(GLfloat distance, GLfloat twist, GLfloat elevation, GLfloat azimuth)
{
glTranslated(0.0, 0.0, -distance);
glRotated(-twist, 0.0, 0.0, 1.0);
glRotated(-elevation, 1.0, 0.0, 0.0);
glRotated(azimuth, 0.0, 0.0, 1.0);
}

//Inicializa las propiedades de la fuente de luz
static void init(void)
{
    GLfloat light_ambient[] = { 0.75, 0.75, 0.75, 1.0 };
    GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat light_position[] = { 0.0, 0.0, 1.0, 0.0 };

    glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
    glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
    glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
    glLightfv (GL_LIGHT0, GL_POSITION, light_position);
    
    glEnable (GL_LIGHTING);
    glEnable (GL_LIGHT0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);
}

void display (void)
{
    //Defino un material Rojo
    GLfloat mat_ambient_toro[] = {0.05, 0.05, 0.05, 1.0f}; 
    GLfloat mat_diffuse_toro[] = { 0.8, 0.0, 0.0, 1.0f};
    GLfloat mat_specular_toro[] = {0.9, 0.8, 0.8, 1.0f};
 
    //Defino un material Azul
    GLfloat mat_ambient_cubo[] = {0.1, 0.1, 0.1, 1.0f}; 
    GLfloat mat_diffuse_cubo[] = {0.0, 0.0, 0.8, 1.0f};
    GLfloat mat_specular_cubo[] = {0.9, 0.9, 0.9, 1.0f};
   
    //Defino un material Verde
    GLfloat mat_ambient_esfera[] = {0.1, 0.1, 0.1, 1.0f}; 
    GLfloat mat_diffuse_esfera[] = {0.0, 0.7, 0.0, 1.0f};
    GLfloat mat_specular_esfera[] = {0.8, 0.8, 0.8, 1.0f};

    GLfloat zExtent, xExtent, xLocal, zLocal;
    int loopX, loopZ;

    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode( GL_MODELVIEW_MATRIX );
    glLoadIdentity();
    polarView(15.0f, giro, elevacion, azimitud);

    //Dibujo la Grilla
    glPushMatrix();
    glPushAttrib( GL_LIGHTING_BIT );
    glDisable( GL_LIGHTING );
    glColor3f( 0.0, 0.7, 0.7 );
    glBegin( GL_LINES );
    zExtent = DEF_floorGridScale * DEF_floorGridZSteps;
    for(loopX = -DEF_floorGridXSteps; loopX <= DEF_floorGridXSteps; loopX++ )
	{
	xLocal = DEF_floorGridScale * loopX;
	glVertex3f( xLocal, 0.0, -zExtent );
	glVertex3f( xLocal, 0.0,  zExtent );
	}
    xExtent = DEF_floorGridScale * DEF_floorGridXSteps;
    for(loopZ = -DEF_floorGridZSteps; loopZ <= DEF_floorGridZSteps; loopZ++ )
	{
	zLocal = DEF_floorGridScale * loopZ;
	glVertex3f( -xExtent, 0.0, zLocal );
	glVertex3f(  xExtent, 0.0, zLocal );
	}
    glEnd();
    glPopAttrib();
    glPopMatrix();

    //Dibuja el Toro
    glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient_toro);
    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse_toro);
    glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular_toro);
    glMaterialf (GL_FRONT, GL_SHININESS, 50.0f);
    glPushMatrix ();
    glTranslatef (-2.0, 1.0, 2.0); 
    glRotatef(-45.0, 0.0, 1.0, 0.0);
    glRotatef(-45.0, 1.0, 0.0, 0.0);
    glutSolidTorus (0.3, 0.8, 12, 24);
    glPopMatrix ();

    //Dibuja el cubo
    glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient_cubo);
    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse_cubo);
    glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular_cubo);
    glMaterialf (GL_FRONT, GL_SHININESS, 100.0f);
    glPushMatrix ();
    glTranslatef (1.0, 1.0, 1.0); 
    glRotatef(15.0, 0.0, 1.0, 0.0);
    glutSolidCube (2.0);
    glPopMatrix ();
    
    //Dibuja la esfera de radio 2.5
    glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient_esfera);
    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse_esfera);
    glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular_esfera);
    glMaterialf (GL_FRONT, GL_SHININESS, 100.0f);
    glPushMatrix ();
    glTranslatef (-1.0, 1.0, 0.0); 
    glutSolidSphere (1.0, 16, 16);
    glPopMatrix ();

    glFlush ();
}

void reshape(int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   gluPerspective(30, (GLfloat) w/(GLfloat) h, 1.0, 200.0);
   glMatrixMode (GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
   case 'x':
   case 'X':
      elevacion = elevacion + 10.0f;
      glutPostRedisplay();
      break;
   case 'v':
   case 'V':
      elevacion = elevacion - 10.0f;
      glutPostRedisplay();
      break;
   case 'y':
   case 'Y':
      azimitud = azimitud + 10.0f;
      glutPostRedisplay();
      break;
   case 'u':
   case 'U':
      azimitud = azimitud - 10.0f;
      glutPostRedisplay();
      break;
   case 'z':
   case 'Z':
      giro = giro + 10.0f;
      glutPostRedisplay();
      break;
   case 'c':
   case 'C':
      giro = giro - 10.0f;
      glutPostRedisplay();
      break;
   case 27:
      exit(0);
      break;
   }
}

int main(int argc, char **argv)
{
   glutInitWindowSize(300, 300);
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
   glutCreateWindow(argv[0]);
   init();
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutDisplayFunc(display);
   glutMainLoop();
   return 0;
}

valcoey@hotmail.com

Ramiro Alcocer, 2001

Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links