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