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

Evaluators

Los Evaluators son primitivas sumisnistradas por OpenGL para evaluación polinomial de curvas y superficies de Bézier.

Los Evaluators de OpenGL nos permiten especificar una superficie solo usando sus puntos de control, podemos crear superficies compuestas por puntos, modelos de alambre (wireframe) o dibujar modelos sombreados (shaded) ya que los vectores normales a la superficie son calculados en forma automatica, y hasta superficies con la aplicacion de Texturas.

El procedimiento para usar evaluators es:

Puntos de Control

Ubicacion de los puntos de control de la superficie de Bézier de 5x5.

Los puntos de control estan dados de la siguiente forma ctrlpoints[5][5][3].

[3]=(0,1,2) me indican las cordenadas x, y, z de cada punto.
[5]=(0,1,2,3,4) columnas, j=0,1,2,3,4.
[5]=(0,1,2,3,4) filas, i=0,1,2,3,4. 

Definir el Evaluators

Usar glMap2f() para definir un Evaluator 2D de OpenGL.

Sintaxis: void glMap2f(GLenum target, TYPEu1, TYPEu2, GLint ustride, GLint uorder, TYPEv1, TYPEv2, GLint vstride, GLint vorder, TYPE points);

En mi ejemplo tenemos:

glMap2f(GL_MAP2_VERTEX_3,0,1,3,5,0,1,15,5,&ctrlpoints[0][0][0])
GL_MAP2_VERTEX_3 = Tipo del punto de control, coordenadas x,y,z de los vertices.
0 = el valor mas bajo del parametro u.
1 = el valor mas alto del parametro u.
5 = dimencion en la direccion u, en este caso 5.
3 = es el numero de datos por punto de control, en este caso 3 ya que tenemos x,y,z.
0 = el valor mas chico de v
1 = el valor mas grande de v.
15 = distancia entre los puntos en ctrlpoints, en este caso 3*5 = 15.
5 =  dimencion en la direccion v.
&ctrlpoints[0][0][0]=es el array que contiene los puntos de control.

Activar el Evaluators

Este se activa con glEnable(GL_MAP2_VERTEX_3)

Tipo de superficie a dibujar

Con glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0), me crea una grilla con 20 puntos que estan comprendidos entre 0.0 y 1.0, eso para u y v.

Bueno con glEvalMesh2(GL_FILL, 0, 20, 0, 20) me dibuja la superficie en modo shaded y con glEvalMesh2(GL_LINE, 0, 20, 0, 20) en modo wireframe (solo lineas).
bezier_wire.jpg bezier_shaded.jpg
Modo wireframe Modo shaded

Con glEnable(GL_AUTO_NORMAL) le indicamos que me calcule en forma automatica las normales, para utilizar el modo de dibujo shaded y con glEnable(GL_NORMALIZE) hace que estas normales esten normalizadas (es decir vectores de modulo 1.0).

Código Fuente

/*
 OpenGL Evaluators
 Autor : Ramiro Alcocer
 Email : valcoey@hotmail.com
 www   : www.oocities.org/valcoey/index.html
*/

#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <math.h>

//puntos de control de la superficie de Bezier
GLfloat ctrlpoints[5][5][3] = {
    {{-2.0, -2.0, 0.5}, 
     {-1.0, -2.0, -0.4}, 
     {0.0, -2.0, -0.5}, 
     {1.0, -2.0, -0.4}, 
     {2.0, -2.0, 0.5}}, 
    {{-2.0, -1.0, 0.5}, 
     {-1.0, -1.0, 0.5}, 
     {0.0, -1.0, 0.75}, 
     {1.0, -1.0, 0.5},
     {2.0, -1.0, 0.25}}, 
    {{-2.0, 0.0, 0.6}, 
     {-1.0, 0.0, 1.0}, 
     {0.0, 0.0, 1.5}, 
     {1.0, 0.0, 1.0},
     {2.0, 0.0, 0.26}}, 
    {{-2.0, 1.0, 0.5}, 
     {-1.0, 1.0, 1.0}, 
     {0.0, 1.0, 1.25}, 
     {1.0, 1.0, 1.0},
     {2.0, 1.0, 0.25}},
    {{-2.0, 2.0, 1.0}, 
     {-1.0, 2.0, 0.5}, 
     {0.0, 2.0,  0.25}, 
     {1.0, 2.0,  0.5},
     {2.0, 2.0, 1.0}}
};

//propiedades del material
GLfloat mat_ambient[] = {0.0f, 0.05f, 0.06f, 1.0f}; 
GLfloat mat_diffuse[] = {0.0f, 0.50980392f, 0.50980392f, 1.0f};
GLfloat mat_specular[] = {0.90196078f, 0.90196078f, 0.90196078f, 1.0f};  

//angulos de rotacion
GLfloat rotx = 0.0;
GLfloat roty = 0.0;
GLfloat rotz = 0.0;

//parametros de la fuente de luz
void initlights(void)
{
 //propiedades de la fuente de luz
 GLfloat ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
 GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
 GLfloat position[] = { 0.0f, 0.0f, 1.0f, 0.0f };

 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
 glLightfv(GL_LIGHT0, GL_POSITION, position);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0);
}

//dibuja los puntos de control de la superficie
void DrawPoints(void)
{
 int i,j; 

 glPushAttrib( GL_LIGHTING_BIT );
 glDisable( GL_LIGHTING );

 //cambio el tamaņo del pexels para hacerlo mas visible
 glPointSize(4.0f);

 //dibujo todos los puntos de control de la superficie
 glColor3f( 0.0, 1.0, 1.0);
 glBegin(GL_POINTS);
 for(j=0; j<5; j++)
    for (i=0; i<5; i++)
       glVertex3fv(ctrlpoints[j][i]);
 glEnd();

 glColor3f( 0.0, 0.25, 0.5);
 glBegin(GL_LINES);
 for (j=0; j<4; j++)
     for (i=0; i<4; i++)
         { 
         glVertex3fv(ctrlpoints[j][i]);
         glVertex3fv(ctrlpoints[j][i+1]);
         }
  for (i=0; i<4; i++)
     for (j=0; j<4; j++)
         { 
         glVertex3fv(ctrlpoints[j][i]);
         glVertex3fv(ctrlpoints[j+1][i]);
         }
 glEnd();

 glPopAttrib();
}


//dibuja la superficie 
void display(void)
{
 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glMatrixMode( GL_MODELVIEW_MATRIX );
 
 glLoadIdentity();
 
 glTranslated(0.0, 0.0, -12.0);
 glRotatef(rotx, 1.0, 0.0, 0.0);
 glRotatef(roty, 0.0, 1.0, 0.0);
 glRotatef(rotz, 0.0, 0.0, 1.0);

 //material para la superficie de Bezier
 glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient);
 glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse);
 glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular);
 glMaterialf (GL_FRONT, GL_SHININESS, 128.0f);
 
 glEvalMesh2(GL_FILL, 0, 20, 0, 20);

 DrawPoints();

 glFlush();
}

void init(void)
{
 glClearColor (0.0, 0.0, 0.0, 1.0);
 glEnable (GL_DEPTH_TEST);
 glMap2f(GL_MAP2_VERTEX_3, 
         0, 1, 3, 5,0, 1, 15, 5, 
         &ctrlpoints[0][0][0]);
 //activa el evaluador
 glEnable(GL_MAP2_VERTEX_3);
 glEnable(GL_AUTO_NORMAL);
 glEnable(GL_NORMALIZE);
 //me crea una grilla de 400 puntos (20x20)
 glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
 initlights();
}

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, 50.0);
 glMatrixMode (GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
   case '1':
      rotx = rotx + 10.0f;
      glutPostRedisplay();
      break;
   case '2':
      rotx = rotx - 10.0f;
      glutPostRedisplay();
      break;
   case '3':
      roty = roty + 10.0f;
      glutPostRedisplay();
      break;
   case '4':
      roty = roty - 10.0f;
      glutPostRedisplay();
      break;
   case '5':
      rotz = rotz + 10.0f;
      glutPostRedisplay();
      break;
   case '6':
      rotz = rotz - 10.0f;
      glutPostRedisplay();
      break;
   case 27:
      exit(0);
      break;
   }
}

int main(int argc, char** argv)
{
 glutInit(&argc, argv);
 glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
 glutInitWindowSize (300, 300);
 glutInitWindowPosition (100, 100);
 glutCreateWindow ("Superficie de Bazier");
 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