smooth.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:13k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*       smooth.c     Nate Robins, 1998     Model viewer program.  Exercises the glm library.  */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <stdarg.h> #include <GL/glut.h> #include "gltb.h" #include "glm.h" #include "dirent32.h" #define DATA_DIR "data/" char*      model_file = NULL; /* name of the obect file */ GLuint     model_list = 0; /* display list for object */ GLMmodel*  model; /* glm model data structure */ GLfloat    scale; /* original scale factor */ GLfloat    smoothing_angle = 90.0; /* smoothing angle */ GLfloat    weld_distance = 0.00001; /* epsilon for welding vertices */ GLboolean  facet_normal = GL_FALSE; /* draw with facet normal? */ GLboolean  bounding_box = GL_FALSE; /* bounding box on? */ GLboolean  performance = GL_FALSE; /* performance counter on? */ GLboolean  stats = GL_FALSE; /* statistics on? */ GLuint     material_mode = 0; /* 0=none, 1=color, 2=material */ GLint      entries = 0; /* entries in model menu */ GLdouble   pan_x = 0.0; GLdouble   pan_y = 0.0; GLdouble   pan_z = 0.0; #if defined(_WIN32) #include <sys/timeb.h> #else #include <limits.h> #include <unistd.h> #include <sys/types.h> #include <sys/times.h> #endif #ifndef CLK_TCK
  2. #define CLK_TCK 1000
  3. #endif
  4. float elapsed(void) {     static long begin = 0;     static long finish, difference; #if defined(_WIN32)     static struct timeb tb;     ftime(&tb);     finish = tb.time*1000+tb.millitm; #else     static struct tms tb;     finish = times(&tb); #endif     difference = finish - begin;     begin = finish;     return (float)difference/(float)CLK_TCK; } void shadowtext(int x, int y, char* s)  {     int lines;     char* p;     glDisable(GL_DEPTH_TEST);     glMatrixMode(GL_PROJECTION);     glPushMatrix();     glLoadIdentity();     glOrtho(0, glutGet(GLUT_WINDOW_WIDTH),      0, glutGet(GLUT_WINDOW_HEIGHT), -1, 1);     glMatrixMode(GL_MODELVIEW);     glPushMatrix();     glLoadIdentity();     glColor3ub(0, 0, 0);     glRasterPos2i(x+1, y-1);     for(p = s, lines = 0; *p; p++) { if (*p == 'n') {     lines++;     glRasterPos2i(x+1, y-1-(lines*18)); } glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);     }     glColor3ub(0, 128, 255);     glRasterPos2i(x, y);     for(p = s, lines = 0; *p; p++) { if (*p == 'n') {     lines++;     glRasterPos2i(x, y-(lines*18)); } glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);     }     glMatrixMode(GL_PROJECTION);     glPopMatrix();     glMatrixMode(GL_MODELVIEW);     glPopMatrix();     glEnable(GL_DEPTH_TEST); } void lists(void) {     GLfloat ambient[] = { 0.2, 0.2, 0.2, 1.0 };     GLfloat diffuse[] = { 0.8, 0.8, 0.8, 1.0 };     GLfloat specular[] = { 0.0, 0.0, 0.0, 1.0 };     GLfloat shininess = 65.0;     glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);     glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);     glMaterialfv(GL_FRONT, GL_SPECULAR, specular);     glMaterialf(GL_FRONT, GL_SHININESS, shininess);     if (model_list) glDeleteLists(model_list, 1);     /* generate a list */     if (material_mode == 0) {  if (facet_normal)     model_list = glmList(model, GLM_FLAT); else     model_list = glmList(model, GLM_SMOOTH);     } else if (material_mode == 1) { if (facet_normal)     model_list = glmList(model, GLM_FLAT | GLM_COLOR); else     model_list = glmList(model, GLM_SMOOTH | GLM_COLOR);     } else if (material_mode == 2) { if (facet_normal)     model_list = glmList(model, GLM_FLAT | GLM_MATERIAL); else     model_list = glmList(model, GLM_SMOOTH | GLM_MATERIAL);     } } void init(void) {     gltbInit(GLUT_LEFT_BUTTON);        /* read in the model */     model = glmReadOBJ(model_file);     scale = glmUnitize(model);     glmFacetNormals(model);     glmVertexNormals(model, smoothing_angle);     if (model->nummaterials > 0) material_mode = 2;     /* create new display lists */     lists();     glEnable(GL_LIGHTING);     glEnable(GL_LIGHT0);     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);     glEnable(GL_DEPTH_TEST);     glEnable(GL_CULL_FACE); } void reshape(int width, int height) {     gltbReshape(width, height);     glViewport(0, 0, width, height);        glMatrixMode(GL_PROJECTION);     glLoadIdentity();     gluPerspective(60.0, (GLfloat)height / (GLfloat)width, 1.0, 128.0);     glMatrixMode(GL_MODELVIEW);     glLoadIdentity();     glTranslatef(0.0, 0.0, -3.0); } #define NUM_FRAMES 5 void display(void) {     static char s[256], t[32];     static char* p;     static int frames = 0;     glClearColor(1.0, 1.0, 1.0, 1.0);     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     glPushMatrix();     glTranslatef(pan_x, pan_y, 0.0);     gltbMatrix(); #if 0   /* glmDraw() performance test */     if (material_mode == 0) {  if (facet_normal)     glmDraw(model, GLM_FLAT); else     glmDraw(model, GLM_SMOOTH);     } else if (material_mode == 1) { if (facet_normal)     glmDraw(model, GLM_FLAT | GLM_COLOR); else     glmDraw(model, GLM_SMOOTH | GLM_COLOR);     } else if (material_mode == 2) { if (facet_normal)     glmDraw(model, GLM_FLAT | GLM_MATERIAL); else     glmDraw(model, GLM_SMOOTH | GLM_MATERIAL);     } #else     glCallList(model_list); #endif     glDisable(GL_LIGHTING);     if (bounding_box) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_CULL_FACE); glColor4f(1.0, 0.0, 0.0, 0.25); glutSolidCube(2.0); glDisable(GL_BLEND);     }     glPopMatrix();     if (stats) { /* XXX - this could be done a _whole lot_ faster... */ int height = glutGet(GLUT_WINDOW_HEIGHT); glColor3ub(0, 0, 0); sprintf(s, "%sn%d verticesn%d trianglesn%d normalsn" "%d texcoordsn%d groupsn%d materials",         model->pathname, model->numvertices, model->numtriangles,  model->numnormals, model->numtexcoords, model->numgroups, model->nummaterials); shadowtext(5, height-(5+18*1), s);     }     /* spit out frame rate. */     frames++;     if (frames > NUM_FRAMES) { sprintf(t, "%g fps", frames/elapsed()); frames = 0;     }     if (performance) { shadowtext(5, 5, t);     }     glutSwapBuffers();     glEnable(GL_LIGHTING); } void keyboard(unsigned char key, int x, int y) {     GLint params[2];     switch (key) {     case 'h': printf("helpnn"); printf("w         -  Toggle wireframe/filledn"); printf("c         -  Toggle cullingn"); printf("n         -  Toggle facet/smooth normaln"); printf("b         -  Toggle bounding boxn"); printf("r         -  Reverse polygon windingn"); printf("m         -  Toggle color/material/none moden"); printf("p         -  Toggle performance indicatorn"); printf("s/S       -  Scale model smaller/largern"); printf("t         -  Show model statsn"); printf("o         -  Weld vertices in modeln"); printf("+/-       -  Increase/decrease smoothing anglen"); printf("W         -  Write model to file (out.obj)n"); printf("q/escape  -  Quitnn"); break;     case 't': stats = !stats; break;     case 'p': performance = !performance; break;     case 'm': material_mode++; if (material_mode > 2)     material_mode = 0; printf("material_mode = %dn", material_mode); lists(); break;     case 'd': glmDelete(model); init(); lists(); break;     case 'w': glGetIntegerv(GL_POLYGON_MODE, params); if (params[0] == GL_FILL)     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;     case 'c': if (glIsEnabled(GL_CULL_FACE))     glDisable(GL_CULL_FACE); else     glEnable(GL_CULL_FACE); break;     case 'b': bounding_box = !bounding_box; break;     case 'n': facet_normal = !facet_normal; lists(); break;     case 'r': glmReverseWinding(model); lists(); break;     case 's': glmScale(model, 0.8); lists(); break;     case 'S': glmScale(model, 1.25); lists(); break;     case 'o': printf("Welded %dn", glmWeld(model, weld_distance)); glmVertexNormals(model, smoothing_angle); lists(); break;     case 'O': weld_distance += 0.01; printf("Weld distance: %.2fn", weld_distance); glmWeld(model, weld_distance); glmFacetNormals(model); glmVertexNormals(model, smoothing_angle); lists(); break;     case '-': smoothing_angle -= 1.0; printf("Smoothing angle: %.1fn", smoothing_angle); glmVertexNormals(model, smoothing_angle); lists(); break;          case '+': smoothing_angle += 1.0; printf("Smoothing angle: %.1fn", smoothing_angle); glmVertexNormals(model, smoothing_angle); lists(); break;          case 'W': glmScale(model, 1.0/scale); glmWriteOBJ(model, "out.obj", GLM_SMOOTH | GLM_MATERIAL); break;     case 'R': {     GLuint i;     GLfloat swap;     for (i = 1; i <= model->numvertices; i++) { swap = model->vertices[3 * i + 1]; model->vertices[3 * i + 1] = model->vertices[3 * i + 2]; model->vertices[3 * i + 2] = -swap;     }     glmFacetNormals(model);     lists();     break; }     case 27: exit(0); break;     }     glutPostRedisplay(); } void menu(int item) {     int i = 0;     DIR* dirp;     char* name;     struct dirent* direntp;     if (item > 0) { keyboard((unsigned char)item, 0, 0);     } else { dirp = opendir(DATA_DIR); while ((direntp = readdir(dirp)) != NULL) {     if (strstr(direntp->d_name, ".obj")) { i++; if (i == -item)     break;     } } if (!direntp)     return; name = (char*)malloc(strlen(direntp->d_name) + strlen(DATA_DIR) + 1); strcpy(name, DATA_DIR); strcat(name, direntp->d_name); model = glmReadOBJ(name); scale = glmUnitize(model); glmFacetNormals(model); glmVertexNormals(model, smoothing_angle); if (model->nummaterials > 0)     material_mode = 2; else     material_mode = 0; lists(); free(name); glutPostRedisplay();     } } static GLint      mouse_state; static GLint      mouse_button; 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) {     int buffering = GLUT_DOUBLE;     struct dirent* direntp;     DIR* dirp;     int models;     glutInitWindowSize(512, 512);     glutInit(&argc, argv);     while (--argc) { if (strcmp(argv[argc], "-sb") == 0)     buffering = GLUT_SINGLE; else     model_file = argv[argc];     }     if (!model_file) { model_file = "data/dolphins.obj";     }     glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | buffering);     glutCreateWindow("Smooth");        glutReshapeFunc(reshape);     glutDisplayFunc(display);     glutKeyboardFunc(keyboard);     glutMouseFunc(mouse);     glutMotionFunc(motion);     models = glutCreateMenu(menu);     dirp = opendir(DATA_DIR);     if (!dirp) { fprintf(stderr, "%s: can't open data directory.n", argv[0]);     } else { while ((direntp = readdir(dirp)) != NULL) {     if (strstr(direntp->d_name, ".obj")) { entries++; glutAddMenuEntry(direntp->d_name, -entries);     } } closedir(dirp);     }     glutCreateMenu(menu);     glutAddMenuEntry("Smooth", 0);     glutAddMenuEntry("", 0);     glutAddSubMenu("Models", models);     glutAddMenuEntry("", 0);     glutAddMenuEntry("[w]   Toggle wireframe/filled", 'w');     glutAddMenuEntry("[c]   Toggle culling on/off", 'c');     glutAddMenuEntry("[n]   Toggle face/smooth normals", 'n');     glutAddMenuEntry("[b]   Toggle bounding box on/off", 'b');     glutAddMenuEntry("[p]   Toggle frame rate on/off", 'p');     glutAddMenuEntry("[t]   Toggle model statistics", 't');     glutAddMenuEntry("[m]   Toggle color/material/none mode", 'm');     glutAddMenuEntry("[r]   Reverse polygon winding", 'r');     glutAddMenuEntry("[s]   Scale model smaller", 's');     glutAddMenuEntry("[S]   Scale model larger", 'S');     glutAddMenuEntry("[o]   Weld redundant vertices", 'o');     glutAddMenuEntry("[+]   Increase smoothing angle", '+');     glutAddMenuEntry("[-]   Decrease smoothing angle", '-');     glutAddMenuEntry("[W]   Write model to file (out.obj)", 'W');     glutAddMenuEntry("", 0);     glutAddMenuEntry("[Esc] Quit", 27);     glutAttachMenu(GLUT_RIGHT_BUTTON);        init();        glutMainLoop();     return 0; }