Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links
Los grupos de suavizado o smooth, determinan que en el objeto se aprecien perfectamente las caras que lo componen o que, por lo contrario, aparesca una superficie lisa dandole mayor calidad al objeto.
El modelo tiene 140 vertices y 276 poligonos, tiene 4 diferentes materiales, y varios grupos de suavizado.
Vertices: 140 -2.565938 2.352102 -6.527843 -2.595936 2.372203 -5.197637 -1.844158 2.311115 -6.988675 ...... ...... ...... 3.885235 -2.020434 -2.251750 -4.062057 -1.503610 0.278006 3.996690 -1.510068 0.255300 Faces: 276 1 4 19 MaterialID: 0 Smoothing: 1 10 41 0 MaterialID: 1 Smoothing: 2 ...... ...... ...... 80 139 136 MaterialID: 2 Smoothing: 3 |
En este ejemplo el modelo tiene aplicado varios materiales las propiedades de estos, se encuentran en un archivo de texto el cual, es leido por el programa, para aplicarlo a cada uno de los poligonos del modelo.
Material: 4 ambient 0.25 0.25 0.25 1.0 diffuse 0.0 0.8 0.25 1.0 specular 1.0 1.0 1.0 1.0 shininess 128.0 ambient 0.25 0.25 0.25 1.0 diffuse 0.0 0.25 1.0 1.0 specular 1.0 1.0 1.0 1.0 shininess 128.0 ambient 0.1745 0.01175 0.01175 1.0 diffuse 0.61424 0.04136 0.04136 1.0 specular 1.0 1.0 1.0 1.0 shininess 100.0 ambient 0.229412 0.123529 0.027451 1.0 diffuse 0.780392 0.568627 0.113725 1.0 specular 1.0 1.0 1.8 1.0 shininess 100.0 |
Codigo Fuente, archivo con los datos del modelo, de los materiales y el ejecutable :
ejemplo4.zip
Las rutinas del manejo del mouse las podes ver en trackball.html.
/* Aplicacion de los grupos de suavizado autor : Alcocer Ramiro emeil : valcoey@hotmail.com www : www.oocities.org/valcoey/index.html */ #include <GL/glut.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include "trackball.h" struct Point3f { float x, y, z; }; struct Face { int material; int vertexIndices[3]; int smoothingGroup; Point3f normal[3]; Point3f faceNormal; }; struct Object3D { int nVertices; Point3f *pVertices; int nFaces; Face *pFaces; }; struct Material { float diffuse[4]; float ambient[4]; float specular[4]; float shininess; }; float LightPos[] = { 0.0f, 0.0f, 1.0f, 0.0f}; float LightAmb[] = { 0.25f, 0.25f, 0.25f, 1.0f}; float LightDif[] = { 1.0f, 1.0f, 1.0f, 1.0f}; float LightSpc[] = { 1.0f, 1.0f, 1.0f, 1.0f}; static GLint mouse_state; static GLint mouse_button; GLdouble pan_x = 0.0; GLdouble pan_y = 0.0; GLdouble pan_z = 0.0; Object3D obj; Material *pMaterial; void ReadMaterial(char *filename) { FILE *f; char line[80]; char mode[15]; char trash[9]; int i,numMaterial; if((f = fopen(filename, "rt"))==NULL) { printf("File Not Found : %s\n",filename); exit(1); } fgets(line, 80, f ); sscanf(line,"%s %d", &mode, &numMaterial); pMaterial= new Material[numMaterial]; for (i=0; i<numMaterial; i++) { fgets(line, 80, f); sscanf(line, "%s %f %f %f %f",&trash, &pMaterial[i].ambient[0], &pMaterial[i].ambient[1], &pMaterial[i].ambient[2], &pMaterial[i].ambient[3]); fgets(line, 80, f); sscanf(line, "%s %f %f %f %f",&trash, &pMaterial[i].diffuse[0], &pMaterial[i].diffuse[1], &pMaterial[i].diffuse[2], &pMaterial[i].diffuse[3]); fgets(line, 80, f); sscanf(line, "%s %f %f %f %f",&trash, &pMaterial[i].specular[0], &pMaterial[i].specular[1], &pMaterial[i].specular[2], &pMaterial[i].specular[3]); fgets(line, 80, f); sscanf(line, "%s %f", &trash, &pMaterial[i].shininess); } fclose(f); } void CargarModelo(char *filename, Object3D &object) { FILE *file; char *tempString = new char [80]; char trash[15]; float tempX, tempY, tempZ; int tempA, tempB, tempC; int indexMaterial, indexSmoothing; int i; if((file = fopen(filename, "rt"))==NULL) { printf("File Not Found : %s\n",filename); exit(1); } while(strncmp(tempString, "Vertices",8)) { fscanf(file, "%s", tempString); if (feof(file)) { printf("String \"Vertices\" no existe\n"); exit(1); } } fgetc(file); fscanf(file, "%d", &object.nVertices); object.pVertices = new Point3f[object.nVertices]; for (i=0; i<object.nVertices; i++) { fscanf(file, "%f %f %f\n", &tempX, &tempY, &tempZ); object.pVertices[i].x=tempX; object.pVertices[i].y=tempY; object.pVertices[i].z=tempZ; } while(strncmp(tempString, "Faces",5)) { fscanf(file, "%s", tempString); if (feof(file)) { printf("String \"Faces\" no existe\n"); exit(1); } } fgetc(file); fscanf(file, "%d", &object.nFaces); object.pFaces = new Face[object.nFaces]; for (i=0; i<object.nFaces; i++) { fscanf(file, "%d %d %d\n", &tempA, &tempB, &tempC); fscanf(file, "%s %d\n", &trash, &indexMaterial); fscanf(file, "%s %d\n", &trash, &indexSmoothing); object.pFaces[i].vertexIndices[0]=tempA; object.pFaces[i].vertexIndices[1]=tempB; object.pFaces[i].vertexIndices[2]=tempC; object.pFaces[i].material=indexMaterial; object.pFaces[i].smoothingGroup=indexSmoothing; } } float Max(float a, float b) { if (b > a) return b; return a; } void CalcularNormales(Object3D &object) { float x1, y1, z1; float x2, y2, z2; float x3, y3, z3; float length; int a, b, c; int i; for (i=0; i<object.nFaces; i++) { Face& face = object.pFaces[i]; a = face.vertexIndices[0]; b = face.vertexIndices[1]; c = face.vertexIndices[2]; x1 = object.pVertices[b].x - object.pVertices[a].x; y1 = object.pVertices[b].y - object.pVertices[a].y; z1 = object.pVertices[b].z - object.pVertices[a].z; x2 = object.pVertices[c].x - object.pVertices[a].x; y2 = object.pVertices[c].y - object.pVertices[a].y; z2 = object.pVertices[c].z - object.pVertices[a].z; z3 = x1*y2 - y1*x2; x3 = y1*z2 - z1*y2; y3 = z1*x2 - x1*z2; length = sqrt(x3*x3 + y3*y3 + z3*z3); if (length == 0) { face.faceNormal.x=1; face.faceNormal.y=1; face.faceNormal.z=1; } else { face.faceNormal.x=x3/length; face.faceNormal.y=y3/length; face.faceNormal.z=z3/length; } face.normal[0].x=face.normal[1].x=face.normal[2].x=face.faceNormal.x; face.normal[0].y=face.normal[1].y=face.normal[2].y=face.faceNormal.y; face.normal[0].z=face.normal[1].z=face.normal[2].z=face.faceNormal.z; } } void applySmoothingGroups(Object3D &object) { int i,j,k,l,smoothingGroup; float length; for (i=0; i<object.nFaces; i++) { smoothingGroup = object.pFaces[i].smoothingGroup; for (j=i+1; j<object.nFaces; j++) { if (smoothingGroup == object.pFaces[j].smoothingGroup) { for (k=0; k<3; k++) { for (l=0; l<3; l++) { if (object.pFaces[i].vertexIndices[k] == object.pFaces[j].vertexIndices[l]) { object.pFaces[i].normal[k].x += object.pFaces[j].faceNormal.x; object.pFaces[i].normal[k].y += object.pFaces[j].faceNormal.y; object.pFaces[i].normal[k].z += object.pFaces[j].faceNormal.z; object.pFaces[j].normal[l].x += object.pFaces[i].faceNormal.x; object.pFaces[j].normal[l].y += object.pFaces[i].faceNormal.y; object.pFaces[j].normal[l].z += object.pFaces[i].faceNormal.z; } } } } } for (k=0; k<3; k++) { length = sqrt(pow(object.pFaces[i].normal[k].x,2.0) + pow(object.pFaces[i].normal[k].y,2.0) + pow(object.pFaces[i].normal[k].z,2.0)); if (length == 0) { object.pFaces[i].normal[k].x = 1; object.pFaces[i].normal[k].y = 1; object.pFaces[i].normal[k].z = 1; } else { object.pFaces[i].normal[k].x /= length; object.pFaces[i].normal[k].y /= length; object.pFaces[i].normal[k].z /= length; } } } } void EscalarModelo(Object3D &object) { int i; float maxx, minx, maxy, miny, maxz, minz; float cx, cy, cz, w, h, d; float scale; maxx = minx = object.pVertices[0].x; maxy = miny = object.pVertices[0].y; maxz = minz = object.pVertices[0].z; for (i=0; i<object.nVertices; i++) { if (maxx < object.pVertices[i].x ) maxx = object.pVertices[i].x; if (minx > object.pVertices[i].x) minx = object.pVertices[i].x; if (maxy < object.pVertices[i].y) maxy = object.pVertices[i].y; if (miny > object.pVertices[i].y ) miny = object.pVertices[i].y; if (maxz < object.pVertices[i].z) maxz = object.pVertices[i].z; if (minz > object.pVertices[i].z) minz = object.pVertices[i].z; } w = (float) (fabs(maxx) + fabs(minx)); h = (float) (fabs(maxy) + fabs(miny)); d = (float) (fabs(maxz) + fabs(minz)); cx = (maxx + minx) / 2.0f; cy = (maxy + miny) / 2.0f; cz = (maxz + minz) / 2.0f; scale = 2.0f/ Max(Max(w, h), d); for (i=0; i<object.nVertices; i++) { object.pVertices[i].x -= cx; object.pVertices[i].y -= cy; object.pVertices[i].z -= cz; object.pVertices[i].x *= scale; object.pVertices[i].y *= scale; object.pVertices[i].z *= scale; } } void killObject(Object3D &object) { delete[] object.pFaces; object.pFaces = NULL; object.nFaces = 0; delete[] object.pVertices; object.pVertices = NULL; object.nVertices = 0; delete[] pMaterial; pMaterial = NULL; } void reshape(int w, int h) { if (!h) return; gltbReshape(w, h); glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -2.5); } void display(void) { int a, b, c; int i; int j; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); gltbMatrix(); glBegin(GL_TRIANGLES); for (i=0; i<obj.nFaces; i++) { const Face& face = obj.pFaces[i]; j=face.material; glMaterialfv(GL_FRONT, GL_AMBIENT, pMaterial[j].ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, pMaterial[j].diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, pMaterial[j].specular); glMaterialf(GL_FRONT, GL_SHININESS, pMaterial[j].shininess); a=face.vertexIndices[0]; b=face.vertexIndices[1]; c=face.vertexIndices[2]; glNormal3f(face.normal[0].x, face.normal[0].y, face.normal[0].z); glVertex3f(obj.pVertices[a].x, obj.pVertices[a].y, obj.pVertices[a].z); glNormal3f(face.normal[1].x, face.normal[1].y, face.normal[1].z); glVertex3f(obj.pVertices[b].x, obj.pVertices[b].y, obj.pVertices[b].z); glNormal3f(face.normal[2].x, face.normal[2].y, face.normal[2].z); glVertex3f(obj.pVertices[c].x, obj.pVertices[c].y, obj.pVertices[c].z); } glEnd(); glPopMatrix(); glFlush(); glutSwapBuffers(); } void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glCullFace(GL_BACK); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glLightfv(GL_LIGHT0, GL_POSITION, LightPos); glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb); glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif); glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpc); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); CargarModelo("ship.dat", obj); ReadMaterial("material.mat"); CalcularNormales(obj); applySmoothingGroups(obj); EscalarModelo(obj); gltbInit(GLUT_MIDDLE_BUTTON); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; } } void mouse(int button, int state, int x, int y) { GLdouble model[4*4]; GLdouble proj[4*4]; GLint view[4]; /* fix for two-button mice -- left mouse + shift = middle mouse */ if (button == GLUT_LEFT_BUTTON && glutGetModifiers() & GLUT_ACTIVE_SHIFT) button = GLUT_MIDDLE_BUTTON; gltbMouse(button, state, x, y); mouse_state = state; mouse_button = button; if (state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON) { glGetDoublev(GL_MODELVIEW_MATRIX, model); glGetDoublev(GL_PROJECTION_MATRIX, proj); glGetIntegerv(GL_VIEWPORT, view); gluProject((GLdouble)x, (GLdouble)y, 0.0, model, proj, view, &pan_x, &pan_y, &pan_z); gluUnProject((GLdouble)x, (GLdouble)y, pan_z, model, proj, view, &pan_x, &pan_y, &pan_z); pan_y = -pan_y; } glutPostRedisplay(); } void motion(int x, int y) { GLdouble model[4*4]; GLdouble proj[4*4]; GLint view[4]; gltbMotion(x, y); if (mouse_state == GLUT_DOWN && mouse_button == GLUT_MIDDLE_BUTTON) { glGetDoublev(GL_MODELVIEW_MATRIX, model); glGetDoublev(GL_PROJECTION_MATRIX, proj); glGetIntegerv(GL_VIEWPORT, view); gluProject((GLdouble)x, (GLdouble)y, 0.0, model, proj, view, &pan_x, &pan_y, &pan_z); gluUnProject((GLdouble)x, (GLdouble)y, pan_z, model, proj, view, &pan_x, &pan_y, &pan_z); pan_y = -pan_y; } glutPostRedisplay(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitWindowSize(400, 400); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("Modelo 3D (smooth)"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glutMotionFunc(motion); glutMainLoop(); killObject(obj); return 0; } |
Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links