Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links
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).
![]() |
Ring Torus (Fig 1) a>b |
![]() |
Horn Torus (Fig 2) a=b |
![]() |
Spindle Torus (Fig 3) a<b |
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.
/*
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