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

Superficies Paramétricas 3D

Las ecuaciones paramétricas del Toro son :

x(u,v)=(a + b*cos(v))*cos(u)

y(u,v)=(a + b*cos(v))*sin(u)

z(u,,v)=b*sin(v)

donde u, v estan entre 0.0 y 2 Pi. el valor de a y de b determina el tipo de Toro, si a>b corresponde al Ring Torus (Fig 1), a=b corresponde al Horn Torus (Fig 2), y si a<b corresponde al Spindle Torus (Fig 3).

toro1.jpg

Ring Torus (Fig 1)

a>b

toro2.jpg

Horn Torus (Fig 2)

a=b

toro3.jpg

Spindle Torus (Fig 3)

a<b

Gráfico de la página de inicio

Ecuaciones parametricas de la superficie

x(u,v)=cos(u)(4+cos(v))

y(u,v)=sin(u)(4+cos(v))

z(u,v)=4 sin(2u) + sin(v)(1.2-sin(v))

utilice, el mismo código del Toro, reemplazando solamente la ecución de la superficie 3D, para obtener dos modelos, uno en modo wireframe, uilizando para ello la opción glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) y el otro en modo shading, con glPolygonMode(GL_FRONT_AND_BACK, GL_FILL), luego combine las dos imagenes utilazando Photoshop.

Código Fuente (Toro)


/*
Autor  = Ramiro Alcocer
email  = valcoey@hotmail.com
web    = www.oocities.org/valcoey/index.html
*/

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

#define PI 		(GLfloat) 3.14159265358979323846
#define usegs		72
#define vsegs		36
#define MaxPuntos	(usegs+1)*(vsegs+1)
#define MaxPoligonos    usegs*vsegs

struct {
        GLfloat fVert1[3];
        GLfloat fVert2[3];
        GLfloat fVert3[3];
        GLfloat fVert4[3];
        GLfloat fNormal[3];
       } Quad[MaxPoligonos];

GLfloat vertice[MaxPuntos][3];
GLfloat vnorms[MaxPuntos][3];
GLint   poli[MaxPoligonos][4];

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

GLint	numPoligonos;
GLint   numVertices;
GLfloat umin, umax;
GLfloat vmin, vmax;

GLint   vertNorms = 0;
GLint   fill      = 1;

/*
Ecuaciones parametricas de la superficie del Toro
x = (a + b*cos(v))*cos(u)
y = (a + b*cos(v))*sin(u)
z = b*sin(v)
dobde 0.0<b<a y 0.0<=v<=2*PI, 0.0<=u<=2*PI
*/

void GenerarPuntos(void)
{
 GLfloat u,v;
 GLfloat a, b;
 GLfloat udelta,vdelta;
 GLint i,j,k;
 
 umin = 0.0f; umax = 2.0f*PI;
 vmin = 0.0f; vmax = 2.0f*PI;
 a = 2.0f;
 b = 1.0f;
 udelta = (umax-umin)/usegs;
 vdelta = (vmax-vmin)/vsegs;
 k = 0;
 u = umin;
 for (j=0; j<=usegs; j++)
    {
    v = vmin;
    for (i=0; i<=vsegs; i++)
        {
        //ecuaciones del Toro
        vertice[k][0] = (a + b*cos(v))*cos(u);
        vertice[k][1] = (a + b*cos(v))*sin(u);
        vertice[k][2] = b*sin(v);

        //de la superficie de la pagina de inicio
	//vertice[k][0]= cos (u) * (4+cos (v));
	//vertice[k][1]= sin (u) * (4+cos (v));
	//vertice[k][2]= 4*sin(2*u) + sin (v)*(1.2-sin (v));

        k += 1;
        v += vdelta;
        }
    u += udelta;
    }
 numVertices = k;
}

void GenerarMalla(void)
{
GLint i,j,k,h;

numPoligonos = 0; 
k=0; h=0;
for (j=0; j<usegs; j++) 
    {
    for (i=0; i<vsegs; i++)
        {
        poli[h][0] = k;
        poli[h][1] = k + 1; 
        poli[h][2] = k + (vsegs + 2);
        poli[h][3] = k + (vsegs + 1);
        h += 1;
        k += 1;
        }
    k += 1;
    }
numPoligonos = h;
}

//Calcula el modulo de un vector
GLfloat Modulo(GLfloat x, GLfloat y, GLfloat z)
{
 GLfloat len;

 len = x*x + y*y + z*z;
 return ( sqrt(len));
}

//Normaliza el vector a mudulo 1
GLvoid Normaliza(GLfloat *x, GLfloat *y, GLfloat *z)
{
 GLfloat len;

 len = Modulo(*x, *y, *z);
 len = 1.0/len;
 (*x) *= len;
 (*y) *= len;
 (*z) *= len;
}

//Calcula el vector Normal
GLvoid CalculateVectorNormal(GLfloat fVert1[], GLfloat fVert2[],
                             GLfloat fVert3[], GLfloat *fNormalX,
                             GLfloat *fNormalY, GLfloat *fNormalZ)
{
 GLfloat Qx, Qy, Qz, Px, Py, Pz;
 Qx = fVert2[0]-fVert1[0];
 Qy = fVert2[1]-fVert1[1];
 Qz = fVert2[2]-fVert1[2];
 Px = fVert3[0]-fVert1[0];
 Py = fVert3[1]-fVert1[1];
 Pz = fVert3[2]-fVert1[2];
 *fNormalX = Py*Qz - Pz*Qy;
 *fNormalY = Pz*Qx - Px*Qz;
 *fNormalZ = Px*Qy - Py*Qx;
}

void CalcularNormales(void)
{
 GLfloat fNormalX, fNormalY, fNormalZ;
 GLfloat sumx=0.0, sumy=0.0, sumz=0.0;
 int shared=0;
 GLint i,j;

 for (i=0; i<numPoligonos; i++)
     {
      //Vertice 1
      j=poli[i][0];
      Quad[i].fVert1[0] = vertice[j][0];
      Quad[i].fVert1[1] = vertice[j][1];
      Quad[i].fVert1[2] = vertice[j][2];
      //Verice 2
      j=poli[i][1];
      Quad[i].fVert2[0] = vertice[j][0];
      Quad[i].fVert2[1] = vertice[j][1];
      Quad[i].fVert2[2] = vertice[j][2];
      //Vertice 3 
      j=poli[i][2];
      Quad[i].fVert3[0] = vertice[j][0];
      Quad[i].fVert3[1] = vertice[j][1];
      Quad[i].fVert3[2] = vertice[j][2];
      //Vertice 4
      j=poli[i][3];
      Quad[i].fVert4[0] = vertice[j][0];
      Quad[i].fVert4[1] = vertice[j][1];
      Quad[i].fVert4[2] = vertice[j][2];

      //Calcula el vector normal al poligono
      CalculateVectorNormal(Quad[i].fVert1, Quad[i].fVert2, Quad[i].fVert3, &fNormalX, &fNormalY, &fNormalZ);
      
      //nos retorna el vector unitario, es decir de modulo 1 
      Normaliza(&fNormalX, &fNormalY, &fNormalZ);
      
      //almacena los vectores normales, para cada poligono
      Quad[i].fNormal[0] = fNormalX;
      Quad[i].fNormal[1] = fNormalY;
      Quad[i].fNormal[2] = fNormalZ;
      };

 for (i=0; i<numVertices; i++)
    {
    for (j=0; j<numPoligonos; j++)
       {
       if (poli[j][0]==i || poli[j][1]==i || poli[j][2]==i || poli[j][3]==i)
           {
           sumx = sumx + Quad[j].fNormal[0];
           sumy = sumy + Quad[j].fNormal[1];
           sumz = sumz + Quad[j].fNormal[2];
           shared ++;
           }
       }
    vnorms[i][0] = sumx / (float) shared;
    vnorms[i][1] = sumy / (float) shared;
    vnorms[i][2] = sumz / (float) shared;
    Normaliza(&vnorms[i][0], &vnorms[i][1], &vnorms[i][2]);
    sumx=0.0;
    sumy=0.0;
    sumz=0.0;
    shared=0.0;
    }
}

static void init(void)
{
 //defino el color y la posicion de la fuente de luz
 GLfloat ambient[] = { 0.8f, 0.8f, 0.8f, 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);
 glEnable(GL_DEPTH_TEST);
 
 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
 GenerarPuntos();
 GenerarMalla();
 CalcularNormales();
}

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);
}

void display(void)
{
 GLfloat mat_ambient[] = {0.1745f, 0.01175f, 0.01175f, 1.0f}; 
 GLfloat mat_diffuse[] = {0.61424f, 0.04136f, 0.04136f, 1.0f};
 GLfloat mat_specular[] = {0.727811f, 0.626959f, 0.626959f, 1.0f};

 GLint i,j;

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

 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);
 
 glBegin(GL_QUADS);
 for (i=0; i<numPoligonos; i++)
        {
        if (!vertNorms)
        	glNormal3fv(Quad[i].fNormal);
        if (vertNorms)
	   {
	   j=poli[i][0];
           glNormal3fv(vnorms[j]);
           };
        glVertex3fv(Quad[i].fVert1);
        if (vertNorms)
           {
    	   j=poli[i][1];
           glNormal3fv(vnorms[j]);
           };
	glVertex3fv(Quad[i].fVert2);
 	if (vertNorms)
           {
           j=poli[i][2];
           glNormal3fv(vnorms[j]);
           };
	glVertex3fv(Quad[i].fVert3);
        if (vertNorms)
           {
           j=poli[i][3];
           glNormal3fv(vnorms[j]);
           };
	glVertex3fv(Quad[i].fVert4);
        }
 glEnd();
 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 'y':
   case 'Y':
      azimitud = azimitud + 10.0f;
      glutPostRedisplay();
      break;
   case 'z':
   case 'Z':
      giro = giro + 10.0f;
      glutPostRedisplay();
      break;
   case 'v':
   case 'V':
      vertNorms = !vertNorms;
      glutPostRedisplay();
      break;
   case 'w':
   case 'W':
      fill = !fill;
      if (fill)
	 {
         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	 glEnable(GL_LIGHTING);
	 }
      else
        {
         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	};
     glutPostRedisplay();
     break;
   case 27:
      exit(0);
      break;
   }
}

int main(int argc, char **argv)
{
   glutInitWindowSize(200, 200);
   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