Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links
Este ejemplo carga y visualiza un objeto desde un archivo de texto, donde en la
primer linea del archivo se indica la cantidad de vertices (numVertices) que
tiene el objeto,y a continución la lista de vértices, un vértice por linea.
Luego de la lista de vértices, viene el número de polígonos del objeto (numPoligonos), y una lista de polígonos, uno por linea, dónde le indico con un indice que vértices forman dicho polígono.
Por ejemplo un cubo centrado en el origen de coordenadas y de arista igual a 20.0, compuesto por 8 vértices y 12 polígonos, el archivo queda :
8 -10.0 -10.0 -10.0 10.00 -10.0 -10.0 -10.0 10.0 -10.0 10.0 10.0 -10.0 -10.0 -10.0 10.0 10.0 -10.0 10.0 -10.0 10.0 10.0 10.0 10.0 10.0 12 0 2 3 3 1 0 4 5 7 7 6 4 0 1 5 5 4 0 1 3 7 7 5 1 3 2 6 6 7 3 2 0 4 4 6 2
Este archivo fue generado apartir de una archivo ASC, utilizando Converción, alli hay un ejemplo de un archivo ASC, creado por 3D Studio MAX.
Este codigo me abre el archivo de texto que contiene los datos del objeto y los carga en memoria, la numero de vertices y poligonos solo esta limitado por la memoria que tengamos disponible.
void GargarPoligonos(char *nombre) { int i; FILE *in = fopen(nombre, "r"); if (!in) return; fscanf(in, "%d\n", &numVertices); for (i = 0; i<numVertices; i++) fscanf(in, "%f %f %f\n", &vertice[i][0], &vertice[i][1], &vertice[i][2]); fscanf(in, "%d\n", &numPoligonos); for (i = 0; i<numPoligonos; i++) fscanf(in, "%d %d %d\n", &poli[i][0], &poli[i][1], &poli[i][2]); fclose(in); }
![]() |
Aqui el objeto se representa en modo WIREFRAME (malla de alambre). |
![]() |
En este caso el objeto es representado en el modo FLAT SHADING, donde cada polígono es coloreado usando la información de su vector normal, para evaluar la luz que recibe, aqui se puede ver claramente los poligonos que forman el objeto. |
![]() |
Si un vértice pertenece a más de un poligono, algo muy común, tendremos que calcular el vector normal de cada uno de los polígonos a los que pertenece el vértice, promediarlo y después normalizar el resultado con lo cuál ese vértice presentará un vector normal al cuál han contribuido todos los poligonos que tenian en comun ese vertice, con esto se logra una mayor calidad, ya que practicamente se elimina la diferencia de color entre los poligonos, se lo suele llamar SMOOTH SHADING |
/* 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 MaxPuntos 2000 #define MaxPoligonos 4000 struct { GLfloat fVert1[3]; GLfloat fVert2[3]; GLfloat fVert3[3]; GLfloat fNormal[3]; } Tri[MaxPoligonos]; GLfloat vertice[MaxPuntos][3]; GLfloat vnorms[MaxPuntos][3]; GLint poli[MaxPoligonos][3]; GLfloat elevacion = 0.0f; GLfloat azimitud = 0.0f; GLfloat giro = 0.0f; GLint numPoligonos; GLint numVertices; GLint vertNorms = 0; GLint fill = 1; void GargarPoligonos(char *nombre) { int i; FILE *in = fopen(nombre, "r"); if (!in) return; fscanf(in, "%d\n", &numVertices); for (i = 0; i<numVertices; i++) fscanf(in, "%f %f %f\n", &vertice[i][0], &vertice[i][1], &vertice[i][2]); fscanf(in, "%d\n", &numPoligonos); for (i = 0; i<numPoligonos; i++) fscanf(in, "%d %d %d\n", &poli[i][0], &poli[i][1], &poli[i][2]); fclose(in); } //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 a un poligono GLvoid CalculateVectorNormal(GLfloat fVert1[], GLfloat fVert2[], GLfloat fVert3[], GLfloat *fNormalX, GLfloat *fNormalY, GLfloat *fNormalZ) { GLfloat Qx, Qy, Qz, Px, Py, Pz; Px = fVert2[0]-fVert1[0]; Py = fVert2[1]-fVert1[1]; Pz = fVert2[2]-fVert1[2]; Qx = fVert3[0]-fVert1[0]; Qy = fVert3[1]-fVert1[1]; Qz = 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]; Tri[i].fVert1[0] = vertice[j][0]; Tri[i].fVert1[1] = vertice[j][1]; Tri[i].fVert1[2] = vertice[j][2]; //Verice 2 j=poli[i][1]; Tri[i].fVert2[0] = vertice[j][0]; Tri[i].fVert2[1] = vertice[j][1]; Tri[i].fVert2[2] = vertice[j][2]; //Vertice 3 j=poli[i][2]; Tri[i].fVert3[0] = vertice[j][0]; Tri[i].fVert3[1] = vertice[j][1]; Tri[i].fVert3[2] = vertice[j][2]; //Calcula el vector normal al poligono CalculateVectorNormal(Tri[i].fVert1, Tri[i].fVert2, Tri[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 Tri[i].fNormal[0] = fNormalX; Tri[i].fNormal[1] = fNormalY; Tri[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 + Tri[j].fNormal[0]; sumy = sumy + Tri[j].fNormal[1]; sumz = sumz + Tri[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[] = { 1.0f, 1.0f, 1.0f, 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); GargarPoligonos("model.dat"); 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.0f, 0.1f, 0.1f, 1.0f}; GLfloat mat_diffuse[] = {0.2f, 0.7f, 0.9f, 1.0f}; GLfloat mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLint i,j; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode( GL_MODELVIEW_MATRIX ); glLoadIdentity(); polarView(450.0f, 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_TRIANGLES); for (i=0; i<numPoligonos; i++) { if (!vertNorms) glNormal3fv(Tri[i].fNormal); if (vertNorms) { j=poli[i][0]; glNormal3fv(vnorms[j]); }; glVertex3fv(Tri[i].fVert1); if (vertNorms) { j=poli[i][1]; glNormal3fv(vnorms[j]); }; glVertex3fv(Tri[i].fVert2); if (vertNorms) { j=poli[i][2]; glNormal3fv(vnorms[j]); }; glVertex3fv(Tri[i].fVert3); } 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, 500.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(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