Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OpenGL:在.obj顶点上绘制球体_Opengl_Geometry_Vertices - Fatal编程技术网

OpenGL:在.obj顶点上绘制球体

OpenGL:在.obj顶点上绘制球体,opengl,geometry,vertices,Opengl,Geometry,Vertices,我在场景中加载了一个.obj立方体,我想在每个顶点(顶点+原点)上绘制一个球体 在my draw()函数中: if(spheres){ i=0, j=0; while (1){ printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]); glTranslatef(model->ver

我在场景中加载了一个.obj立方体,我想在每个顶点(顶点+原点)上绘制一个球体

在my draw()函数中:

if(spheres){
    i=0, j=0;
    while (1){
            printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
            glTranslatef(model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
            glColor3f(0.0, 0.0, 1.0);
            glutSolidSphere(0.4, 5, 5);
            if(j >= model->numvertices)
                break;
            i=i+3;
            j++;
        }
}
“模型”在哪里

GLMmodel*  model;               /* glm model data structure */

但当我画它们时,它们的位置不正确

在上图中,我“手动”绘制它们:

没有成功

所有代码:

/*  
    gc_smooth.c
    Nate Robins, 1998
    Giulio Casciola, 2008

    Model viewer program.  Exercises the glm library.
*/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <GL/glut.h>
#include "gltb.h"
#include "glm.h"
#include "dirent32.h"

#pragma comment( linker, "/entry:\"mainCRTStartup\"" )  // set the entry point to be main()

#define DATA_DIR "data/"
#define NUM_FRAMES 5

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  spheres = GL_FALSE;
GLboolean  performance = GL_FALSE;  /* performance counter on? */
GLboolean  stats = GL_FALSE;        /* statistics on? */
GLuint     material_mode = 0;       /* 0=none, 1=color, 2=material, 3=texture */
GLint      entries = 0;         /* entries in model menu */
GLdouble   pan_x = 0.0;
GLdouble   pan_y = 0.0;
GLdouble   pan_z = 0.0;
char texnames[1][64] = {"foto_rgb.ppm"};
//char texnames[1][64] = {"grid.ppm"};
GLint w,h;
GLubyte* texture;


#define CLK_TCK 1000

#if defined(_WIN32)
#include <sys/timeb.h>
#else
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/times.h>
#endif

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);

    glDisable(GL_TEXTURE_2D);
    /* generate a list */
    switch (material_mode)
    {
     case 0:
        if (facet_normal)
            model_list = glmList(model, GLM_FLAT);
        else
            model_list = glmList(model, GLM_SMOOTH);
     break;
     case 1:
        if (facet_normal)
            model_list = glmList(model, GLM_FLAT | GLM_COLOR);
        else
            model_list = glmList(model, GLM_SMOOTH | GLM_COLOR);
     break;
     case 2:
        if (facet_normal)
            model_list = glmList(model, GLM_FLAT | GLM_MATERIAL);
        else
            model_list = glmList(model, GLM_SMOOTH | GLM_MATERIAL);
     break;
     case 3:
        glEnable(GL_TEXTURE_2D);
        model_list = glmList(model, GLM_TEXTURE);
//        glDisable(GL_TEXTURE_2D);
     break;
    }
}

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);
}

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);
}

void display(void){
    static char s[256], t[32];
    static char* p;
    static int frames = 0;
    int i=0,j=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 */
    swith(material_mode)
    {
     case 0:
        if (facet_normal)
            glmDraw(model, GLM_FLAT);
        else
            glmDraw(model, GLM_SMOOTH);
     break;
     case 1:
        if (facet_normal)
            glmDraw(model, GLM_FLAT | GLM_COLOR);
        else
            glmDraw(model, GLM_SMOOTH | GLM_COLOR);
     break;
     case 2:
        if (facet_normal)
            glmDraw(model, GLM_FLAT | GLM_MATERIAL);
        else
            glmDraw(model, GLM_SMOOTH | GLM_MATERIAL);
     break;
     case 3:
        glEnable(GL_TEXTURE_2D);
        glmDraw(model, GLM_TEXTURE );
//        glDisable(GL_TEXTURE_2D);
     break;
    }
#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);
    }

    if(spheres){
        //i=0, j=0;
        //while (1){
                printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
                glTranslatef(-1.000000, -1.000000, 1.000000);
                glColor3f(0.0, 0.0, 1.0);
                glutSolidSphere(0.3, 5, 5);
                glTranslatef(-1.000000, 1.000000, 1.000000);
                glColor3f(0.0, 0.0, 1.0);
                glutSolidSphere(0.3, 5, 5);
                //if(j >= model->numvertices)
                //    break;
                //i=i+3;
                //j++;
            //}
    }

    glPopMatrix();

    if (stats) {
        /* XXX - this could be done a _whole lot_ faster... */
        int height = glutGet(GLUT_WINDOW_HEIGHT);
        glColor3ub(0, 0, 0);
        sprintf(s, "%s\n%d vertices\n%d triangles\n%d normals\n"
            "%d texcoords\n%d groups\n%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("help\n\n");
        printf("w         -  Toggle wireframe/filled\n");
        printf("c         -  Toggle culling\n");
        printf("n         -  Toggle facet/smooth normal\n");
        printf("b         -  Toggle bounding box\n");
        printf("r         -  Reverse polygon winding\n");
        printf("m         -  Toggle color/material/none/texture mode\n");
        printf("p         -  Toggle performance indicator\n");
        printf("s/S       -  Scale model smaller/larger\n");
        printf("t         -  Show model stats\n");
        printf("o         -  Weld vertices in model\n");
        printf("+/-       -  Increase/decrease smoothing angle\n");
        printf("W         -  Write model to file (out.obj)\n");
        printf("q/escape  -  Quit\n\n");
        break;

    case 't':
        stats = !stats;
        break;

    case 'p':
        performance = !performance;
        break;

    case 'm':
        material_mode++;
        if (material_mode > 3)
            material_mode = 0;
        printf("material_mode = %d\n", 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 %d\n", glmWeld(model, weld_distance));
        glmVertexNormals(model, smoothing_angle);
        lists();
        break;

    case 'O':
        weld_distance += 0.01;
        printf("Weld distance: %.2f\n", weld_distance);
        glmWeld(model, weld_distance);
        glmFacetNormals(model);
        glmVertexNormals(model, smoothing_angle);
        lists();
        break;

    case '-':
        smoothing_angle -= 1.0;
        printf("Smoothing angle: %.1f\n", smoothing_angle);
        glmVertexNormals(model, smoothing_angle);
        lists();
        break;

    case '+':
        smoothing_angle += 1.0;
        printf("Smoothing angle: %.1f\n", 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 'v':
        {
            spheres = !spheres;
            /*printf("Il modello ha %u vertici \n", model->numvertices);
            int i=0, j=0;
            while (1){
                printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
                if(j >= model->numvertices)
                    break;
                i=i+3;
                j++;
            }*/
            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();
}

/* ppmRead: read a PPM raw (type P6) file.  The PPM file has a header
   that should look something like:

     P6
     # comment
     width height max_value
     rgbrgbrgb...

   where "P6" is the magic cookie which identifies the file type and
   should be the only characters on the first line followed by a
   carriage return.  Any line starting with a # mark will be treated
   as a comment and discarded.  After the magic cookie, three integer
   values are expected: width, height of the image and the maximum
   value for a pixel (max_value must be < 256 for PPM raw files).  The
   data section consists of width*height rgb triplets (one byte each)
   in binary format (i.e., such as that written with fwrite() or
   equivalent).

   The rgb data is returned as an array of unsigned chars (packed
   rgb).  The malloc()'d memory should be free()'d by the caller.  If
   an error occurs, an error message is sent to stderr and NULL is
   returned.

*/
unsigned char* 
ppmRead(char* filename, int* width, int* height)
{
    FILE* fp;
    int i, w, h, d;
    unsigned char* image;
    char head[70];          /* max line <= 70 in PPM (per spec). */

    fp = fopen(filename, "rb");
    if (!fp) {
    perror(filename);
    return NULL;
    }

    /* grab first two chars of the file and make sure that it has the
       correct magic cookie for a raw PPM file. */
    fgets(head, 70, fp);
    if (strncmp(head, "P6", 2)) {
    fprintf(stderr, "%s: Not a raw PPM file\n", filename);
    return NULL;
    }

    /* grab the three elements in the header (width, height, maxval). */
    i = 0;
    while(i < 3) {
    fgets(head, 70, fp);
    if (head[0] == '#')     /* skip comments. */
        continue;
    if (i == 0)
        i += sscanf(head, "%d %d %d", &w, &h, &d);
    else if (i == 1)
        i += sscanf(head, "%d %d", &h, &d);
    else if (i == 2)
        i += sscanf(head, "%d", &d);
    }

    /* grab all the image data in one fell swoop. */
    image = (unsigned char*)malloc(sizeof(unsigned char)*w*h*3);
    fread(image, sizeof(unsigned char), w*h*3, fp);
    fclose(fp);

    *width = w;
    *height = h;
    return image;
}

textures(void)
{
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

/* XXX - RE bug - must enable texture before bind. */
   glEnable(GL_TEXTURE_2D);

   glBindTexture(GL_TEXTURE_2D, 1);
   texture = (GLubyte*)ppmRead(texnames[0], &w, &h);
//   glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0,
//   GL_RGB, GL_UNSIGNED_BYTE, texture);
   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h,
             GL_RGB, GL_UNSIGNED_BYTE, texture);
   free(texture);

/* XXX - RE bug - must enable texture before bind. */
   glDisable(GL_TEXTURE_2D);
}

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";
        model_file = "data/boeing_2.obj";
    }

    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | buffering);
    glutCreateWindow("Smooth");

    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);

/* Image data packed tightly. */
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    textures();

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
//    glEnable(GL_TEXTURE_2D);

    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/texture 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;
}
/*
gc_光滑
内特·罗宾斯,1998年
朱利奥·卡斯基奥拉,2008年
模型查看器程序。练习glm库。
*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“gltb.h”
#包括“glm.h”
#包括“dirent32.h”
#pragma comment(链接器,“/entry:\”mainCRTStartup\”//将入口点设置为main()
#定义数据目录“数据/”
#定义NUM_帧5
char*model_file=NULL;/*obect文件的名称*/
GLuint model_list=0;/*对象的显示列表*/
GLMmodel*模型;/*glm模型数据结构*/
GLfloat刻度;/*原始比例因子*/
GLfloat平滑_角度=90.0;/*平滑角*/
GLfloat焊缝_距离=0.00001;/*焊接顶点的ε*/
GLboolean facet_normal=GL_FALSE;/*用刻面法线绘制*/
GLboolean边界框=GL_假;/*边界框打开了吗*/
GL布尔球体=GL_假;
GLboolean性能=GL_FALSE;/*性能计数器打开了吗*/
GLboolean stats=GL_FALSE;/*统计数字*/
胶合材料_模式=0;/*0=无,1=颜色,2=材质,3=纹理*/
闪烁条目=0;/*“模型”菜单中的条目*/
GLdouble pan_x=0.0;
GLdouble pan_y=0.0;
GLdouble pan_z=0.0;
char texnames[1][64]={“foto_rgb.ppm”};
//char texnames[1][64]={“grid.ppm”};
闪烁w,h;
GLubyte*纹理;
#定义CLK_TCK 1000
#如果已定义(_WIN32)
#包括
#否则
#包括
#包括
#包括
#包括
#恩迪夫
浮动(无效){
静态长开始=0;
静电长余辉,差异;
#如果已定义(_WIN32)
静态结构timeb-tb;
ftime&tb;
完成=tb.time*1000+tb.millitm;
#否则
静态结构tms-tb;
完成=次数(&tb);
#恩迪夫
差异=完成-开始;
开始=结束;
返回(浮动)差/(浮动)时钟;
}
无效阴影文本(整数x,整数y,字符*s){
内线;
char*p;
glDisable(GLU深度测试);
glMatrixMode(GL_投影);
glPushMatrix();
glLoadIdentity();
glOrtho(0,glutGet(GLUT_窗口_宽度),
0,glutGet(GLUT\U窗口\U高度),-1,1;
glMatrixMode(GLU模型视图);
glPushMatrix();
glLoadIdentity();
GL3UB(0,0,0);
glRasterPos2i(x+1,y-1);
对于(p=s,行=0;*p;p++){
如果(*p=='\n'){
行++;
glRasterPos2i(x+1,y-1-(第18行));
}
glutBitmapCharacter(GLUT_位图_HELVETICA_18,*p);
}
glColor3ub(0、128、255);
glRasterPos2i(x,y);
对于(p=s,行=0;*p;p++){
如果(*p=='\n'){
行++;
glRasterPos2i(x,y-(第18行));
}
glutBitmapCharacter(GLUT_位图_HELVETICA_18,*p);
}
glMatrixMode(GL_投影);
glPopMatrix();
glMatrixMode(GLU模型视图);
glPopMatrix();
glEnable(GLU深度试验);
}
作废清单(作废){
GLfloat环境[]={0.2,0.2,0.2,1.0};
GLfloat diffuse[]={0.8,0.8,0.8,1.0};
GLfloat镜面反射[]={0.0,0.0,0.0,1.0};
GLfloat光泽度=65.0;
GLMATERIALV(GL_前部、GL_环境、环境);
GLMATERIALV(GL_前部、GL_漫反射、漫反射);
GLMATERIALV(GL_前部、GL_镜面反射、镜面反射);
GLMATERALF(GLU正面、GLU反光、反光);
if(型号列表)
GLDeleteList(型号列表,1);
glDisable(GL_纹理_2D);
/*生成一个列表*/
开关(物料模式)
{
案例0:
如果(面_正常)
模型列表=glmList(模型,GLM平面);
其他的
模型列表=glmList(模型,GLM平滑);
打破
案例1:
如果(面_正常)
模型列表=glmList(模型,GLM平面| GLM颜色);
其他的
模型列表=glmList(模型,GLM_平滑| GLM_颜色);
打破
案例2:
如果(面_正常)
模型列表=glmList(模型、GLM平面材料);
其他的
模型列表=glmList(模型,GLM_平滑| GLM_材质);
打破
案例3:
glEnable(GL_纹理_2D);
模型列表=glmList(模型、GLM纹理);
//glDisable(GL_纹理_2D);
打破
}
}
void init(void){
gltbInit(GLUT_左按钮);
/*读入模型*/
模型=glmReadOBJ(模型文件);
比例=通用化(模型);
glmFacetNormals(模型);
glmVertexNormals(模型、平滑角度);
如果(型号->材料>0)
物料_模式=2;
/*创建新的显示列表*/
列表();
glEnable(德国劳埃德大学照明);
glEnable(GL_LIGHT0);
glLightModeli(GL_灯光_模型_双面,GL_真);
glEnable(GLU深度试验);
}
空洞重塑(整型宽度、整型高度){
GLTBReformate(宽度、高度);
glViewport(0,0,宽度,高度);
glMatrixMode(GL_投影);
glLoadIdentity();
GLU透视图(60.0,(GLfloat)高度/(GLfloat)宽度,1.0,128.0);
glMatrixMode(GLU模型视图);
glLoadIdentity();
glTranslatef(0.0,0.0,-3.0);
}
作废显示(作废){
静态字符s[256],t[32];
静态字符*p;
静态int帧=0;
int i=0,j=0;
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
glPushMatrix();
glTranslatef(pan_x,pan_y,0.0);
gltbMatrix();
#如果0/*glmDraw()性能测试*/
swith(物料_模式)
{
案例0:
如果(面_正常)
glmDraw(模型,GLM_平面);
其他的
glmDraw(模型,GLM_平滑);
打破
案例1:
如果(面_正常)
glmDraw(型号、GLM|U平面、GLM|U颜色);
其他的
glmDraw(模型,GLM|U平滑| GLM|U颜色);
打破
案例2:
如果(面_正常)
glmDraw(型号、GLM|U扁平材料);
其他的
glTranslatef(-1.000000, -1.000000, 1.000000);
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(0.3, 5, 5);

glTranslatef(-1.000000, 1.000000, 1.000000);
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(0.3, 5, 5);
/*  
    gc_smooth.c
    Nate Robins, 1998
    Giulio Casciola, 2008

    Model viewer program.  Exercises the glm library.
*/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <GL/glut.h>
#include "gltb.h"
#include "glm.h"
#include "dirent32.h"

#pragma comment( linker, "/entry:\"mainCRTStartup\"" )  // set the entry point to be main()

#define DATA_DIR "data/"
#define NUM_FRAMES 5

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  spheres = GL_FALSE;
GLboolean  performance = GL_FALSE;  /* performance counter on? */
GLboolean  stats = GL_FALSE;        /* statistics on? */
GLuint     material_mode = 0;       /* 0=none, 1=color, 2=material, 3=texture */
GLint      entries = 0;         /* entries in model menu */
GLdouble   pan_x = 0.0;
GLdouble   pan_y = 0.0;
GLdouble   pan_z = 0.0;
char texnames[1][64] = {"foto_rgb.ppm"};
//char texnames[1][64] = {"grid.ppm"};
GLint w,h;
GLubyte* texture;


#define CLK_TCK 1000

#if defined(_WIN32)
#include <sys/timeb.h>
#else
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/times.h>
#endif

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);

    glDisable(GL_TEXTURE_2D);
    /* generate a list */
    switch (material_mode)
    {
     case 0:
        if (facet_normal)
            model_list = glmList(model, GLM_FLAT);
        else
            model_list = glmList(model, GLM_SMOOTH);
     break;
     case 1:
        if (facet_normal)
            model_list = glmList(model, GLM_FLAT | GLM_COLOR);
        else
            model_list = glmList(model, GLM_SMOOTH | GLM_COLOR);
     break;
     case 2:
        if (facet_normal)
            model_list = glmList(model, GLM_FLAT | GLM_MATERIAL);
        else
            model_list = glmList(model, GLM_SMOOTH | GLM_MATERIAL);
     break;
     case 3:
        glEnable(GL_TEXTURE_2D);
        model_list = glmList(model, GLM_TEXTURE);
//        glDisable(GL_TEXTURE_2D);
     break;
    }
}

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);
}

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);
}

void display(void){
    static char s[256], t[32];
    static char* p;
    static int frames = 0;
    int i=0,j=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 */
    swith(material_mode)
    {
     case 0:
        if (facet_normal)
            glmDraw(model, GLM_FLAT);
        else
            glmDraw(model, GLM_SMOOTH);
     break;
     case 1:
        if (facet_normal)
            glmDraw(model, GLM_FLAT | GLM_COLOR);
        else
            glmDraw(model, GLM_SMOOTH | GLM_COLOR);
     break;
     case 2:
        if (facet_normal)
            glmDraw(model, GLM_FLAT | GLM_MATERIAL);
        else
            glmDraw(model, GLM_SMOOTH | GLM_MATERIAL);
     break;
     case 3:
        glEnable(GL_TEXTURE_2D);
        glmDraw(model, GLM_TEXTURE );
//        glDisable(GL_TEXTURE_2D);
     break;
    }
#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);
    }

    if(spheres){
        //i=0, j=0;
        //while (1){
                printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
                glTranslatef(-1.000000, -1.000000, 1.000000);
                glColor3f(0.0, 0.0, 1.0);
                glutSolidSphere(0.3, 5, 5);
                glTranslatef(-1.000000, 1.000000, 1.000000);
                glColor3f(0.0, 0.0, 1.0);
                glutSolidSphere(0.3, 5, 5);
                //if(j >= model->numvertices)
                //    break;
                //i=i+3;
                //j++;
            //}
    }

    glPopMatrix();

    if (stats) {
        /* XXX - this could be done a _whole lot_ faster... */
        int height = glutGet(GLUT_WINDOW_HEIGHT);
        glColor3ub(0, 0, 0);
        sprintf(s, "%s\n%d vertices\n%d triangles\n%d normals\n"
            "%d texcoords\n%d groups\n%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("help\n\n");
        printf("w         -  Toggle wireframe/filled\n");
        printf("c         -  Toggle culling\n");
        printf("n         -  Toggle facet/smooth normal\n");
        printf("b         -  Toggle bounding box\n");
        printf("r         -  Reverse polygon winding\n");
        printf("m         -  Toggle color/material/none/texture mode\n");
        printf("p         -  Toggle performance indicator\n");
        printf("s/S       -  Scale model smaller/larger\n");
        printf("t         -  Show model stats\n");
        printf("o         -  Weld vertices in model\n");
        printf("+/-       -  Increase/decrease smoothing angle\n");
        printf("W         -  Write model to file (out.obj)\n");
        printf("q/escape  -  Quit\n\n");
        break;

    case 't':
        stats = !stats;
        break;

    case 'p':
        performance = !performance;
        break;

    case 'm':
        material_mode++;
        if (material_mode > 3)
            material_mode = 0;
        printf("material_mode = %d\n", 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 %d\n", glmWeld(model, weld_distance));
        glmVertexNormals(model, smoothing_angle);
        lists();
        break;

    case 'O':
        weld_distance += 0.01;
        printf("Weld distance: %.2f\n", weld_distance);
        glmWeld(model, weld_distance);
        glmFacetNormals(model);
        glmVertexNormals(model, smoothing_angle);
        lists();
        break;

    case '-':
        smoothing_angle -= 1.0;
        printf("Smoothing angle: %.1f\n", smoothing_angle);
        glmVertexNormals(model, smoothing_angle);
        lists();
        break;

    case '+':
        smoothing_angle += 1.0;
        printf("Smoothing angle: %.1f\n", 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 'v':
        {
            spheres = !spheres;
            /*printf("Il modello ha %u vertici \n", model->numvertices);
            int i=0, j=0;
            while (1){
                printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
                if(j >= model->numvertices)
                    break;
                i=i+3;
                j++;
            }*/
            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();
}

/* ppmRead: read a PPM raw (type P6) file.  The PPM file has a header
   that should look something like:

     P6
     # comment
     width height max_value
     rgbrgbrgb...

   where "P6" is the magic cookie which identifies the file type and
   should be the only characters on the first line followed by a
   carriage return.  Any line starting with a # mark will be treated
   as a comment and discarded.  After the magic cookie, three integer
   values are expected: width, height of the image and the maximum
   value for a pixel (max_value must be < 256 for PPM raw files).  The
   data section consists of width*height rgb triplets (one byte each)
   in binary format (i.e., such as that written with fwrite() or
   equivalent).

   The rgb data is returned as an array of unsigned chars (packed
   rgb).  The malloc()'d memory should be free()'d by the caller.  If
   an error occurs, an error message is sent to stderr and NULL is
   returned.

*/
unsigned char* 
ppmRead(char* filename, int* width, int* height)
{
    FILE* fp;
    int i, w, h, d;
    unsigned char* image;
    char head[70];          /* max line <= 70 in PPM (per spec). */

    fp = fopen(filename, "rb");
    if (!fp) {
    perror(filename);
    return NULL;
    }

    /* grab first two chars of the file and make sure that it has the
       correct magic cookie for a raw PPM file. */
    fgets(head, 70, fp);
    if (strncmp(head, "P6", 2)) {
    fprintf(stderr, "%s: Not a raw PPM file\n", filename);
    return NULL;
    }

    /* grab the three elements in the header (width, height, maxval). */
    i = 0;
    while(i < 3) {
    fgets(head, 70, fp);
    if (head[0] == '#')     /* skip comments. */
        continue;
    if (i == 0)
        i += sscanf(head, "%d %d %d", &w, &h, &d);
    else if (i == 1)
        i += sscanf(head, "%d %d", &h, &d);
    else if (i == 2)
        i += sscanf(head, "%d", &d);
    }

    /* grab all the image data in one fell swoop. */
    image = (unsigned char*)malloc(sizeof(unsigned char)*w*h*3);
    fread(image, sizeof(unsigned char), w*h*3, fp);
    fclose(fp);

    *width = w;
    *height = h;
    return image;
}

textures(void)
{
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

/* XXX - RE bug - must enable texture before bind. */
   glEnable(GL_TEXTURE_2D);

   glBindTexture(GL_TEXTURE_2D, 1);
   texture = (GLubyte*)ppmRead(texnames[0], &w, &h);
//   glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0,
//   GL_RGB, GL_UNSIGNED_BYTE, texture);
   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h,
             GL_RGB, GL_UNSIGNED_BYTE, texture);
   free(texture);

/* XXX - RE bug - must enable texture before bind. */
   glDisable(GL_TEXTURE_2D);
}

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";
        model_file = "data/boeing_2.obj";
    }

    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | buffering);
    glutCreateWindow("Smooth");

    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);

/* Image data packed tightly. */
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    textures();

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
//    glEnable(GL_TEXTURE_2D);

    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/texture 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;
}
if(spheres){
    i=0, j=0;
    while (1){
            printf("%d : %f %f %f\n", j, model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
            glPushMatrix();
            glTranslatef(model->vertices[i], model->vertices[i+1], model->vertices[i+2]);
            glColor3f(0.0, 0.0, 1.0);
            glutSolidSphere(0.4, 5, 5);
            glPopMatrix();
            if(j >= model->numvertices)
                break;
            i=i+3;
            j++;
        }
}