Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members   Search  

/home/mrm/Simex/simulations/hr_bike/glm.cxx File Reference

#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <FL/glut.H>
#include "glm.H"

Include dependency graph for glm.cxx:

Include dependency graph

Compounds

struct  _GLMnode

Defines

#define T(x)   model->triangles[(x)]

Typedefs

typedef _GLMnode GLMnode

Enumerations

enum  { X, Y, Z, W }

Functions

char * stralloc (const char *string)
GLfloat _glmMax (GLfloat a, GLfloat b)
GLfloat _glmAbs (GLfloat f)
GLfloat _glmDot (GLfloat *u, GLfloat *v)
GLvoid _glmCross (GLfloat *u, GLfloat *v, GLfloat *n)
GLvoid _glmNormalize (GLfloat *n)
GLboolean _glmEqual (GLfloat *u, GLfloat *v, GLfloat epsilon)
GLfloat * _glmWeldVectors (GLfloat *vectors, GLuint *numvectors, GLfloat epsilon)
GLMgroup * _glmFindGroup (GLMmodel *model, char *name)
GLMgroup * _glmAddGroup (GLMmodel *model, char *name)
GLuint _glmFindMaterial (GLMmodel *model, char *name)
char * _glmDirName (char *path)
GLvoid _glmReadMTL (GLMmodel *model, char *name)
GLvoid _glmWriteMTL (GLMmodel *model, char *modelpath, char *mtllibname)
GLvoid _glmFirstPass (GLMmodel *model, FILE *file)
GLvoid _glmSecondPass (GLMmodel *model, FILE *file)
GLfloat glmUnitize (GLMmodel *model)
GLvoid glmDimensions (GLMmodel *model, GLfloat *dimensions)
GLvoid glmScale (GLMmodel *model, GLfloat scale)
GLvoid glmReverseWinding (GLMmodel *model)
GLvoid glmFacetNormals (GLMmodel *model)
GLvoid glmVertexNormals (GLMmodel *model, GLfloat angle)
GLvoid glmLinearTexture (GLMmodel *model)
GLvoid glmSpheremapTexture (GLMmodel *model)
GLvoid glmDelete (GLMmodel *model)
GLMmodel * glmReadOBJ (char *filename)
GLvoid glmWriteOBJ (GLMmodel *model, char *filename, GLuint mode)
GLvoid glmDraw (GLMmodel *model, GLuint mode)
GLuint glmList (GLMmodel *model, GLuint mode)
GLvoid glmWeld (GLMmodel *model, GLfloat epsilon)

Define Documentation

#define T      model->triangles[(x)]
 


Typedef Documentation

typedef struct _GLMnode GLMnode
 


Enumeration Type Documentation

anonymous enum
 

Enumeration values:
X 
Y 
Z 
W 

00030 { X, Y, Z, W };                 /* elements of a vertex */


Function Documentation

char* stralloc const char *    string [static]
 

00049 {
00050   char *copy;
00051 
00052   copy = (char *) malloc(strlen(string) + 1);
00053   if (copy == NULL)
00054     return NULL;
00055   strcpy(copy, string);
00056   return copy;
00057 }

GLfloat _glmMax GLfloat    a,
GLfloat    b
[static]
 

00064 {
00065   if (a > b)
00066     return a;
00067   return b;
00068 }

GLfloat _glmAbs GLfloat    f [static]
 

00073 {
00074   if (f < 0)
00075     return -f;
00076   return f;
00077 }

GLfloat _glmDot GLfloat *    u,
GLfloat *    v
[static]
 

00086 {
00087   assert(u);
00088   assert(v);
00089 
00090   /* compute the dot product */
00091   return u[X] * v[X] + u[Y] * v[Y] + u[Z] * v[Z];
00092 }

GLvoid _glmCross GLfloat *    u,
GLfloat *    v,
GLfloat *    n
[static]
 

00102 {
00103   assert(u);
00104   assert(v);
00105   assert(n);
00106 
00107   /* compute the cross product (u x v for right-handed [ccw]) */
00108   n[X] = u[Y] * v[Z] - u[Z] * v[Y];
00109   n[Y] = u[Z] * v[X] - u[X] * v[Z];
00110   n[Z] = u[X] * v[Y] - u[Y] * v[X];
00111 }

GLvoid _glmNormalize GLfloat *    n [static]
 

00119 {
00120   GLfloat l;
00121 
00122   assert(n);
00123 
00124   /* normalize */
00125   l = (GLfloat)sqrt(n[X] * n[X] + n[Y] * n[Y] + n[Z] * n[Z]);
00126   n[0] /= l;
00127   n[1] /= l;
00128   n[2] /= l;
00129 }

GLboolean _glmEqual GLfloat *    u,
GLfloat *    v,
GLfloat    epsilon
[static]
 

00140 {
00141   if (_glmAbs(u[0] - v[0]) < epsilon &&
00142       _glmAbs(u[1] - v[1]) < epsilon &&
00143       _glmAbs(u[2] - v[2]) < epsilon) 
00144   {
00145     return GL_TRUE;
00146   }
00147   return GL_FALSE;
00148 }

GLfloat* _glmWeldVectors GLfloat *    vectors,
GLuint *    numvectors,
GLfloat    epsilon
 

00160 {
00161   GLfloat* copies;
00162   GLuint   copied;
00163   GLuint   i, j;
00164 
00165   copies = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (*numvectors + 1));
00166   memcpy(copies, vectors, (sizeof(GLfloat) * 3 * (*numvectors + 1)));
00167 
00168   copied = 1;
00169   for (i = 1; i <= *numvectors; i++) {
00170     for (j = 1; j <= copied; j++) {
00171       if (_glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {
00172         goto duplicate;
00173       }
00174     }
00175 
00176     /* must not be any duplicates -- add to the copies array */
00177     copies[3 * copied + 0] = vectors[3 * i + 0];
00178     copies[3 * copied + 1] = vectors[3 * i + 1];
00179     copies[3 * copied + 2] = vectors[3 * i + 2];
00180     j = copied;                         /* pass this along for below */
00181     copied++;
00182 
00183   duplicate:
00184     /* set the first component of this vector to point at the correct
00185        index into the new copies array */
00186     vectors[3 * i + 0] = (GLfloat)j;
00187   }
00188 
00189   *numvectors = copied-1;
00190   return copies;
00191 }

GLMgroup* _glmFindGroup GLMmodel *    model,
char *    name
 

00197 {
00198   GLMgroup* group;
00199 
00200   assert(model);
00201 
00202   group = model->groups;
00203   while(group) {
00204     if (!strcmp(name, group->name))
00205       break;
00206     group = group->next;
00207   }
00208 
00209   return group;
00210 }

GLMgroup* _glmAddGroup GLMmodel *    model,
char *    name
 

00216 {
00217   GLMgroup* group;
00218 
00219   group = _glmFindGroup(model, name);
00220   if (!group) {
00221     group = (GLMgroup*)malloc(sizeof(GLMgroup));
00222     group->name = stralloc(name);
00223     group->material = 0;
00224     group->numtriangles = 0;
00225     group->triangles = NULL;
00226     group->next = model->groups;
00227     model->groups = group;
00228     model->numgroups++;
00229   }
00230 
00231   return group;
00232 }

GLuint _glmFindMaterial GLMmodel *    model,
char *    name
 

00238 {
00239   GLuint i;
00240 
00241   for (i = 0; i < model->nummaterials; i++) {
00242     if (!strcmp(model->materials[i].name, name))
00243       goto found;
00244   }
00245 
00246   /* didn't find the name, so set it as the default material */
00247   printf("_glmFindMaterial():  can't find material \"%s\".\n", name);
00248   i = 0;
00249 
00250 found:
00251   return i;
00252 }

char* _glmDirName char *    path [static]
 

00263 {
00264   char* dir;
00265   char* s;
00266 
00267   dir = stralloc(path);
00268 
00269   s = strrchr(dir, '/');
00270   if (s)
00271     s[1] = '\0';
00272   else
00273     dir[0] = '\0';
00274 
00275   return dir;
00276 }

GLvoid _glmReadMTL GLMmodel *    model,
char *    name
[static]
 

00286 {
00287   FILE* file;
00288   char* dir;
00289   char* filename;
00290   char  buf[128];
00291   GLuint nummaterials, i;
00292 
00293   dir = _glmDirName(model->pathname);
00294   filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1));
00295   strcpy(filename, dir);
00296   strcat(filename, name);
00297   free(dir);
00298 
00299   /* open the file */
00300   file = fopen(filename, "r");
00301   if (!file) {
00302     fprintf(stderr, "_glmReadMTL() failed: can't open material file \"%s\".\n",
00303             filename);
00304     exit(1);
00305   }
00306   free(filename);
00307 
00308   /* count the number of materials in the file */
00309   nummaterials = 1;
00310   while(fscanf(file, "%s", buf) != EOF) {
00311     switch(buf[0]) {
00312     case '#':                           /* comment */
00313       /* eat up rest of line */
00314       fgets(buf, sizeof(buf), file);
00315       break;
00316     case 'n':                           /* newmtl */
00317       fgets(buf, sizeof(buf), file);
00318       nummaterials++;
00319       sscanf(buf, "%s %s", buf, buf);
00320       break;
00321     default:
00322       /* eat up rest of line */
00323       fgets(buf, sizeof(buf), file);
00324       break;
00325     }
00326   }
00327 
00328   rewind(file);
00329 
00330   /* allocate memory for the materials */
00331   model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * nummaterials);
00332   model->nummaterials = nummaterials;
00333 
00334   /* set the default material */
00335   for (i = 0; i < nummaterials; i++) {
00336     model->materials[i].name = NULL;
00337     model->materials[i].shininess = 0;
00338     model->materials[i].diffuse[0] = 0.8;
00339     model->materials[i].diffuse[1] = 0.8;
00340     model->materials[i].diffuse[2] = 0.8;
00341     model->materials[i].diffuse[3] = 1.0;
00342     model->materials[i].ambient[0] = 0.2;
00343     model->materials[i].ambient[1] = 0.2;
00344     model->materials[i].ambient[2] = 0.2;
00345     model->materials[i].ambient[3] = 1.0;
00346     model->materials[i].specular[0] = 0.0;
00347     model->materials[i].specular[1] = 0.0;
00348     model->materials[i].specular[2] = 0.0;
00349     model->materials[i].specular[3] = 1.0;
00350   }
00351   model->materials[0].name = stralloc("default");
00352 
00353   /* now, read in the data */
00354   nummaterials = 0;
00355   while(fscanf(file, "%s", buf) != EOF) {
00356     switch(buf[0]) {
00357     case '#':                           /* comment */
00358       /* eat up rest of line */
00359       fgets(buf, sizeof(buf), file);
00360       break;
00361     case 'n':                           /* newmtl */
00362       fgets(buf, sizeof(buf), file);
00363       sscanf(buf, "%s %s", buf, buf);
00364       nummaterials++;
00365       model->materials[nummaterials].name = stralloc(buf);
00366       break;
00367     case 'N':
00368       fscanf(file, "%f", &model->materials[nummaterials].shininess);
00369       /* wavefront shininess is from [0, 1000], so scale for OpenGL */
00370       model->materials[nummaterials].shininess /= 1000.0;
00371       model->materials[nummaterials].shininess *= 128.0;
00372       break;
00373     case 'K':
00374       switch(buf[1]) {
00375       case 'd':
00376         fscanf(file, "%f %f %f",
00377                &model->materials[nummaterials].diffuse[0],
00378                &model->materials[nummaterials].diffuse[1],
00379                &model->materials[nummaterials].diffuse[2]);
00380         break;
00381       case 's':
00382         fscanf(file, "%f %f %f",
00383                &model->materials[nummaterials].specular[0],
00384                &model->materials[nummaterials].specular[1],
00385                &model->materials[nummaterials].specular[2]);
00386         break;
00387       case 'a':
00388         fscanf(file, "%f %f %f",
00389                &model->materials[nummaterials].ambient[0],
00390                &model->materials[nummaterials].ambient[1],
00391                &model->materials[nummaterials].ambient[2]);
00392         break;
00393       default:
00394         /* eat up rest of line */
00395         fgets(buf, sizeof(buf), file);
00396         break;
00397       }
00398       break;
00399     default:
00400       /* eat up rest of line */
00401       fgets(buf, sizeof(buf), file);
00402       break;
00403     }
00404   }
00405 }

GLvoid _glmWriteMTL GLMmodel *    model,
char *    modelpath,
char *    mtllibname
[static]
 

00415 {
00416   FILE* file;
00417   char* dir;
00418   char* filename;
00419   GLMmaterial* material;
00420   GLuint i;
00421 
00422   dir = _glmDirName(modelpath);
00423   filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(mtllibname)));
00424   strcpy(filename, dir);
00425   strcat(filename, mtllibname);
00426   free(dir);
00427 
00428   /* open the file */
00429   file = fopen(filename, "w");
00430   if (!file) {
00431     fprintf(stderr, "_glmWriteMTL() failed: can't open file \"%s\".\n",
00432             filename);
00433     exit(1);
00434   }
00435   free(filename);
00436 
00437   /* spit out a header */
00438   fprintf(file, "#  \n");
00439   fprintf(file, "#  Wavefront MTL generated by GLM library\n");
00440   fprintf(file, "#  \n");
00441   fprintf(file, "#  GLM library copyright (C) 1997 by Nate Robins\n");
00442   fprintf(file, "#  email: ndr@pobox.com\n");
00443   fprintf(file, "#  www:   http://www.pobox.com/~ndr\n");
00444   fprintf(file, "#  \n\n");
00445 
00446   for (i = 0; i < model->nummaterials; i++) {
00447     material = &model->materials[i];
00448     fprintf(file, "newmtl %s\n", material->name);
00449     fprintf(file, "Ka %f %f %f\n", 
00450             material->ambient[0], material->ambient[1], material->ambient[2]);
00451     fprintf(file, "Kd %f %f %f\n", 
00452             material->diffuse[0], material->diffuse[1], material->diffuse[2]);
00453     fprintf(file, "Ks %f %f %f\n", 
00454             material->specular[0],material->specular[1],material->specular[2]);
00455     fprintf(file, "Ns %f\n", material->shininess);
00456     fprintf(file, "\n");
00457   }
00458 }

GLvoid _glmFirstPass GLMmodel *    model,
FILE *    file
[static]
 

00469 {
00470   GLuint    numvertices;                /* number of vertices in model */
00471   GLuint    numnormals;                 /* number of normals in model */
00472   GLuint    numtexcoords;               /* number of texcoords in model */
00473   GLuint    numtriangles;               /* number of triangles in model */
00474   GLMgroup* group;                      /* current group */
00475   unsigned  v, n, t;
00476   char      buf[128];
00477 
00478   /* make a default group */
00479   group = _glmAddGroup(model, "default");
00480 
00481   numvertices = numnormals = numtexcoords = numtriangles = 0;
00482   while(fscanf(file, "%s", buf) != EOF) {
00483     switch(buf[0]) {
00484     case '#':                           /* comment */
00485       /* eat up rest of line */
00486       fgets(buf, sizeof(buf), file);
00487       break;
00488     case 'v':                           /* v, vn, vt */
00489       switch(buf[1]) {
00490       case '\0':                        /* vertex */
00491         /* eat up rest of line */
00492         fgets(buf, sizeof(buf), file);
00493         numvertices++;
00494         break;
00495       case 'n':                         /* normal */
00496         /* eat up rest of line */
00497         fgets(buf, sizeof(buf), file);
00498         numnormals++;
00499         break;
00500       case 't':                         /* texcoord */
00501         /* eat up rest of line */
00502         fgets(buf, sizeof(buf), file);
00503         numtexcoords++;
00504         break;
00505       default:
00506         printf("_glmFirstPass(): Unknown token \"%s\".\n", buf);
00507         exit(1);
00508         break;
00509       }
00510       break;
00511     case 'm':
00512       fgets(buf, sizeof(buf), file);
00513       sscanf(buf, "%s %s", buf, buf);
00514       model->mtllibname = stralloc(buf);
00515       _glmReadMTL(model, buf);
00516       break;
00517     case 'u':
00518       /* eat up rest of line */
00519       fgets(buf, sizeof(buf), file);
00520       break;
00521     case 'g':                           /* group */
00522       /* eat up rest of line */
00523       fgets(buf, sizeof(buf), file);
00524       sscanf(buf, "%[^\t\n\r]", buf);
00525       group = _glmAddGroup(model, buf);
00526       break;
00527     case 'f':                           /* face */
00528       v = n = t = 0;
00529       fscanf(file, "%s", buf);
00530       /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
00531       if (strstr(buf, "//")) {
00532         /* v//n */
00533         sscanf(buf, "%d//%d", &v, &n);
00534         fscanf(file, "%d//%d", &v, &n);
00535         fscanf(file, "%d//%d", &v, &n);
00536         numtriangles++;
00537         group->numtriangles++;
00538         while(fscanf(file, "%d//%d", &v, &n) > 0) {
00539           numtriangles++;
00540           group->numtriangles++;
00541         }
00542       } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
00543         /* v/t/n */
00544         fscanf(file, "%d/%d/%d", &v, &t, &n);
00545         fscanf(file, "%d/%d/%d", &v, &t, &n);
00546         numtriangles++;
00547         group->numtriangles++;
00548         while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
00549           numtriangles++;
00550           group->numtriangles++;
00551         }
00552       } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
00553         /* v/t */
00554         fscanf(file, "%d/%d", &v, &t);
00555         fscanf(file, "%d/%d", &v, &t);
00556         numtriangles++;
00557         group->numtriangles++;
00558         while(fscanf(file, "%d/%d", &v, &t) > 0) {
00559           numtriangles++;
00560           group->numtriangles++;
00561         }
00562       } else {
00563         /* v */
00564         fscanf(file, "%d", &v);
00565         fscanf(file, "%d", &v);
00566         numtriangles++;
00567         group->numtriangles++;
00568         while(fscanf(file, "%d", &v) > 0) {
00569           numtriangles++;
00570           group->numtriangles++;
00571         }
00572       }
00573       break;
00574 
00575     default:
00576       /* eat up rest of line */
00577       fgets(buf, sizeof(buf), file);
00578       break;
00579     }
00580   }
00581 
00582 #if 0
00583   /* announce the model statistics */
00584   printf(" Vertices: %d\n", numvertices);
00585   printf(" Normals: %d\n", numnormals);
00586   printf(" Texcoords: %d\n", numtexcoords);
00587   printf(" Triangles: %d\n", numtriangles);
00588   printf(" Groups: %d\n", model->numgroups);
00589 #endif
00590 
00591   /* set the stats in the model structure */
00592   model->numvertices  = numvertices;
00593   model->numnormals   = numnormals;
00594   model->numtexcoords = numtexcoords;
00595   model->numtriangles = numtriangles;
00596 
00597   /* allocate memory for the triangles in each group */
00598   group = model->groups;
00599   while(group) {
00600     group->triangles = (GLuint*)malloc(sizeof(GLuint) * group->numtriangles);
00601     group->numtriangles = 0;
00602     group = group->next;
00603   }
00604 }

GLvoid _glmSecondPass GLMmodel *    model,
FILE *    file
[static]
 

00614 {
00615   GLuint    numvertices;                /* number of vertices in model */
00616   GLuint    numnormals;                 /* number of normals in model */
00617   GLuint    numtexcoords;               /* number of texcoords in model */
00618   GLuint    numtriangles;               /* number of triangles in model */
00619   GLfloat*  vertices;                   /* array of vertices  */
00620   GLfloat*  normals;                    /* array of normals */
00621   GLfloat*  texcoords;                  /* array of texture coordinates */
00622   GLMgroup* group;                      /* current group pointer */
00623   GLuint    material;                   /* current material */
00624   GLuint    v, n, t;
00625   char      buf[128];
00626 
00627   /* set the pointer shortcuts */
00628   vertices     = model->vertices;
00629   normals      = model->normals;
00630   texcoords    = model->texcoords;
00631   group        = model->groups;
00632 
00633   /* on the second pass through the file, read all the data into the
00634      allocated arrays */
00635   numvertices = numnormals = numtexcoords = 1;
00636   numtriangles = 0;
00637   material = 0;
00638   while(fscanf(file, "%s", buf) != EOF) {
00639     switch(buf[0]) {
00640     case '#':                           /* comment */
00641       /* eat up rest of line */
00642       fgets(buf, sizeof(buf), file);
00643       break;
00644     case 'v':                           /* v, vn, vt */
00645       switch(buf[1]) {
00646       case '\0':                        /* vertex */
00647         fscanf(file, "%f %f %f", 
00648                &vertices[3 * numvertices + X], 
00649                &vertices[3 * numvertices + Y], 
00650                &vertices[3 * numvertices + Z]);
00651         numvertices++;
00652         break;
00653       case 'n':                         /* normal */
00654         fscanf(file, "%f %f %f", 
00655                &normals[3 * numnormals + X],
00656                &normals[3 * numnormals + Y], 
00657                &normals[3 * numnormals + Z]);
00658         numnormals++;
00659         break;
00660       case 't':                         /* texcoord */
00661         fscanf(file, "%f %f", 
00662                &texcoords[2 * numtexcoords + X],
00663                &texcoords[2 * numtexcoords + Y]);
00664         numtexcoords++;
00665         break;
00666       }
00667       break;
00668     case 'u':
00669       fgets(buf, sizeof(buf), file);
00670       sscanf(buf, "%s %s", buf, buf);
00671       group->material = material = _glmFindMaterial(model, buf);
00672       break;
00673     case 'g':                           /* group */
00674       /* eat up rest of line */
00675       fgets(buf, sizeof(buf), file);
00676       sscanf(buf, "%[^\t\r\n]", buf);
00677       group = _glmFindGroup(model, buf);
00678       group->material = material;
00679       break;
00680     case 'f':                           /* face */
00681       v = n = t = 0;
00682       fscanf(file, "%s", buf);
00683       /* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
00684       if (strstr(buf, "//")) {
00685         /* v//n */
00686         sscanf(buf, "%d//%d", &v, &n);
00687         T(numtriangles).vindices[0] = v;
00688         T(numtriangles).nindices[0] = n;
00689         fscanf(file, "%d//%d", &v, &n);
00690         T(numtriangles).vindices[1] = v;
00691         T(numtriangles).nindices[1] = n;
00692         fscanf(file, "%d//%d", &v, &n);
00693         T(numtriangles).vindices[2] = v;
00694         T(numtriangles).nindices[2] = n;
00695         group->triangles[group->numtriangles++] = numtriangles;
00696         numtriangles++;
00697         while(fscanf(file, "%d//%d", &v, &n) > 0) {
00698           T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
00699           T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
00700           T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
00701           T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
00702           T(numtriangles).vindices[2] = v;
00703           T(numtriangles).nindices[2] = n;
00704           group->triangles[group->numtriangles++] = numtriangles;
00705           numtriangles++;
00706         }
00707       } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
00708         /* v/t/n */
00709         T(numtriangles).vindices[0] = v;
00710         T(numtriangles).tindices[0] = t;
00711         T(numtriangles).nindices[0] = n;
00712         fscanf(file, "%d/%d/%d", &v, &t, &n);
00713         T(numtriangles).vindices[1] = v;
00714         T(numtriangles).tindices[1] = t;
00715         T(numtriangles).nindices[1] = n;
00716         fscanf(file, "%d/%d/%d", &v, &t, &n);
00717         T(numtriangles).vindices[2] = v;
00718         T(numtriangles).tindices[2] = t;
00719         T(numtriangles).nindices[2] = n;
00720         group->triangles[group->numtriangles++] = numtriangles;
00721         numtriangles++;
00722         while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
00723           T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
00724           T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
00725           T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
00726           T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
00727           T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
00728           T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
00729           T(numtriangles).vindices[2] = v;
00730           T(numtriangles).tindices[2] = t;
00731           T(numtriangles).nindices[2] = n;
00732           group->triangles[group->numtriangles++] = numtriangles;
00733           numtriangles++;
00734         }
00735       } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
00736         /* v/t */
00737         T(numtriangles).vindices[0] = v;
00738         T(numtriangles).tindices[0] = t;
00739         fscanf(file, "%d/%d", &v, &t);
00740         T(numtriangles).vindices[1] = v;
00741         T(numtriangles).tindices[1] = t;
00742         fscanf(file, "%d/%d", &v, &t);
00743         T(numtriangles).vindices[2] = v;
00744         T(numtriangles).tindices[2] = t;
00745         group->triangles[group->numtriangles++] = numtriangles;
00746         numtriangles++;
00747         while(fscanf(file, "%d/%d", &v, &t) > 0) {
00748           T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
00749           T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
00750           T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
00751           T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
00752           T(numtriangles).vindices[2] = v;
00753           T(numtriangles).tindices[2] = t;
00754           group->triangles[group->numtriangles++] = numtriangles;
00755           numtriangles++;
00756         }
00757       } else {
00758         /* v */
00759         sscanf(buf, "%d", &v);
00760         T(numtriangles).vindices[0] = v;
00761         fscanf(file, "%d", &v);
00762         T(numtriangles).vindices[1] = v;
00763         fscanf(file, "%d", &v);
00764         T(numtriangles).vindices[2] = v;
00765         group->triangles[group->numtriangles++] = numtriangles;
00766         numtriangles++;
00767         while(fscanf(file, "%d", &v) > 0) {
00768           T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
00769           T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
00770           T(numtriangles).vindices[2] = v;
00771           group->triangles[group->numtriangles++] = numtriangles;
00772           numtriangles++;
00773         }
00774       }
00775       break;
00776 
00777     default:
00778       /* eat up rest of line */
00779       fgets(buf, sizeof(buf), file);
00780       break;
00781     }
00782   }
00783 
00784 #if 0
00785   /* announce the memory requirements */
00786   printf(" Memory: %d bytes\n",
00787          numvertices  * 3*sizeof(GLfloat) +
00788          numnormals   * 3*sizeof(GLfloat) * (numnormals ? 1 : 0) +
00789          numtexcoords * 3*sizeof(GLfloat) * (numtexcoords ? 1 : 0) +
00790          numtriangles * sizeof(GLMtriangle));
00791 #endif
00792 }

GLfloat glmUnitize GLMmodel *    model
 

00807 {
00808   GLuint  i;
00809   GLfloat maxx, minx, maxy, miny, maxz, minz;
00810   GLfloat cx, cy, cz, w, h, d;
00811   GLfloat scale;
00812 
00813   assert(model);
00814   assert(model->vertices);
00815 
00816   /* get the max/mins */
00817   maxx = minx = model->vertices[3 + X];
00818   maxy = miny = model->vertices[3 + Y];
00819   maxz = minz = model->vertices[3 + Z];
00820   for (i = 1; i <= model->numvertices; i++) {
00821     if (maxx < model->vertices[3 * i + X])
00822       maxx = model->vertices[3 * i + X];
00823     if (minx > model->vertices[3 * i + X])
00824       minx = model->vertices[3 * i + X];
00825 
00826     if (maxy < model->vertices[3 * i + Y])
00827       maxy = model->vertices[3 * i + Y];
00828     if (miny > model->vertices[3 * i + Y])
00829       miny = model->vertices[3 * i + Y];
00830 
00831     if (maxz < model->vertices[3 * i + Z])
00832       maxz = model->vertices[3 * i + Z];
00833     if (minz > model->vertices[3 * i + Z])
00834       minz = model->vertices[3 * i + Z];
00835   }
00836 
00837   /* calculate model width, height, and depth */
00838   w = _glmAbs(maxx) + _glmAbs(minx);
00839   h = _glmAbs(maxy) + _glmAbs(miny);
00840   d = _glmAbs(maxz) + _glmAbs(minz);
00841 
00842   /* calculate center of the model */
00843   cx = (maxx + minx) / 2.0;
00844   cy = (maxy + miny) / 2.0;
00845   cz = (maxz + minz) / 2.0;
00846 
00847   /* calculate unitizing scale factor */
00848   scale = 2.0 / _glmMax(_glmMax(w, h), d);
00849 
00850   /* translate around center then scale */
00851   for (i = 1; i <= model->numvertices; i++) {
00852     model->vertices[3 * i + X] -= cx;
00853     model->vertices[3 * i + Y] -= cy;
00854     model->vertices[3 * i + Z] -= cz;
00855     model->vertices[3 * i + X] *= scale;
00856     model->vertices[3 * i + Y] *= scale;
00857     model->vertices[3 * i + Z] *= scale;
00858   }
00859 
00860   return scale;
00861 }

GLvoid glmDimensions GLMmodel *    model,
GLfloat *    dimensions
 

00871 {
00872   GLuint i;
00873   GLfloat maxx, minx, maxy, miny, maxz, minz;
00874 
00875   assert(model);
00876   assert(model->vertices);
00877   assert(dimensions);
00878 
00879   /* get the max/mins */
00880   maxx = minx = model->vertices[3 + X];
00881   maxy = miny = model->vertices[3 + Y];
00882   maxz = minz = model->vertices[3 + Z];
00883   for (i = 1; i <= model->numvertices; i++) {
00884     if (maxx < model->vertices[3 * i + X])
00885       maxx = model->vertices[3 * i + X];
00886     if (minx > model->vertices[3 * i + X])
00887       minx = model->vertices[3 * i + X];
00888 
00889     if (maxy < model->vertices[3 * i + Y])
00890       maxy = model->vertices[3 * i + Y];
00891     if (miny > model->vertices[3 * i + Y])
00892       miny = model->vertices[3 * i + Y];
00893 
00894     if (maxz < model->vertices[3 * i + Z])
00895       maxz = model->vertices[3 * i + Z];
00896     if (minz > model->vertices[3 * i + Z])
00897       minz = model->vertices[3 * i + Z];
00898   }
00899 
00900   /* calculate model width, height, and depth */
00901   dimensions[X] = _glmAbs(maxx) + _glmAbs(minx);
00902   dimensions[Y] = _glmAbs(maxy) + _glmAbs(miny);
00903   dimensions[Z] = _glmAbs(maxz) + _glmAbs(minz);
00904 }

GLvoid glmScale GLMmodel *    model,
GLfloat    scale
 

00913 {
00914   GLuint i;
00915 
00916   for (i = 1; i <= model->numvertices; i++) {
00917     model->vertices[3 * i + X] *= scale;
00918     model->vertices[3 * i + Y] *= scale;
00919     model->vertices[3 * i + Z] *= scale;
00920   }
00921 }

GLvoid glmReverseWinding GLMmodel *    model
 

00931 {
00932   GLuint i, swap;
00933 
00934   assert(model);
00935 
00936   for (i = 0; i < model->numtriangles; i++) {
00937     swap = T(i).vindices[0];
00938     T(i).vindices[0] = T(i).vindices[2];
00939     T(i).vindices[2] = swap;
00940 
00941     if (model->numnormals) {
00942       swap = T(i).nindices[0];
00943       T(i).nindices[0] = T(i).nindices[2];
00944       T(i).nindices[2] = swap;
00945     }
00946 
00947     if (model->numtexcoords) {
00948       swap = T(i).tindices[0];
00949       T(i).tindices[0] = T(i).tindices[2];
00950       T(i).tindices[2] = swap;
00951     }
00952   }
00953 
00954   /* reverse facet normals */
00955   for (i = 1; i <= model->numfacetnorms; i++) {
00956     model->facetnorms[3 * i + X] = -model->facetnorms[3 * i + X];
00957     model->facetnorms[3 * i + Y] = -model->facetnorms[3 * i + Y];
00958     model->facetnorms[3 * i + Z] = -model->facetnorms[3 * i + Z];
00959   }
00960 
00961   /* reverse vertex normals */
00962   for (i = 1; i <= model->numnormals; i++) {
00963     model->normals[3 * i + X] = -model->normals[3 * i + X];
00964     model->normals[3 * i + Y] = -model->normals[3 * i + Y];
00965     model->normals[3 * i + Z] = -model->normals[3 * i + Z];
00966   }
00967 }

GLvoid glmFacetNormals GLMmodel *    model
 

00977 {
00978   GLuint  i;
00979   GLfloat u[3];
00980   GLfloat v[3];
00981   
00982   assert(model);
00983   assert(model->vertices);
00984 
00985   /* clobber any old facetnormals */
00986   if (model->facetnorms)
00987     free(model->facetnorms);
00988 
00989   /* allocate memory for the new facet normals */
00990   model->numfacetnorms = model->numtriangles;
00991   model->facetnorms = (GLfloat*)malloc(sizeof(GLfloat) *
00992                                        3 * (model->numfacetnorms + 1));
00993 
00994   for (i = 0; i < model->numtriangles; i++) {
00995     model->triangles[i].findex = i+1;
00996 
00997     u[X] = model->vertices[3 * T(i).vindices[1] + X] -
00998            model->vertices[3 * T(i).vindices[0] + X];
00999     u[Y] = model->vertices[3 * T(i).vindices[1] + Y] -
01000            model->vertices[3 * T(i).vindices[0] + Y];
01001     u[Z] = model->vertices[3 * T(i).vindices[1] + Z] -
01002            model->vertices[3 * T(i).vindices[0] + Z];
01003 
01004     v[X] = model->vertices[3 * T(i).vindices[2] + X] -
01005            model->vertices[3 * T(i).vindices[0] + X];
01006     v[Y] = model->vertices[3 * T(i).vindices[2] + Y] -
01007            model->vertices[3 * T(i).vindices[0] + Y];
01008     v[Z] = model->vertices[3 * T(i).vindices[2] + Z] -
01009            model->vertices[3 * T(i).vindices[0] + Z];
01010 
01011     _glmCross(u, v, &model->facetnorms[3 * (i+1)]);
01012     _glmNormalize(&model->facetnorms[3 * (i+1)]);
01013   }
01014 }

GLvoid glmVertexNormals GLMmodel *    model,
GLfloat    angle
 

01034 {
01035   GLMnode*  node;
01036   GLMnode*  tail;
01037   GLMnode** members;
01038   GLfloat*  normals;
01039   GLuint    numnormals;
01040   GLfloat   average[3];
01041   GLfloat   dot, cos_angle;
01042   GLuint    i, avg;
01043 
01044   assert(model);
01045   assert(model->facetnorms);
01046 
01047   /* calculate the cosine of the angle (in degrees) */
01048   cos_angle = cos(angle * M_PI / 180.0);
01049 
01050   /* nuke any previous normals */
01051   if (model->normals)
01052     free(model->normals);
01053 
01054   /* allocate space for new normals */
01055   model->numnormals = model->numtriangles * 3; /* 3 normals per triangle */
01056   model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1));
01057 
01058   /* allocate a structure that will hold a linked list of triangle
01059      indices for each vertex */
01060   members = (GLMnode**)malloc(sizeof(GLMnode*) * (model->numvertices + 1));
01061   for (i = 1; i <= model->numvertices; i++)
01062     members[i] = NULL;
01063   
01064   /* for every triangle, create a node for each vertex in it */
01065   for (i = 0; i < model->numtriangles; i++) {
01066     node = (GLMnode*)malloc(sizeof(GLMnode));
01067     node->index = i;
01068     node->next  = members[T(i).vindices[0]];
01069     members[T(i).vindices[0]] = node;
01070 
01071     node = (GLMnode*)malloc(sizeof(GLMnode));
01072     node->index = i;
01073     node->next  = members[T(i).vindices[1]];
01074     members[T(i).vindices[1]] = node;
01075 
01076     node = (GLMnode*)malloc(sizeof(GLMnode));
01077     node->index = i;
01078     node->next  = members[T(i).vindices[2]];
01079     members[T(i).vindices[2]] = node;
01080   }
01081 
01082   /* calculate the average normal for each vertex */
01083   numnormals = 1;
01084   for (i = 1; i <= model->numvertices; i++) {
01085     /* calculate an average normal for this vertex by averaging the
01086        facet normal of every triangle this vertex is in */
01087     node = members[i];
01088     if (!node)
01089       fprintf(stderr, "glmVertexNormals(): vertex w/o a triangle\n");
01090     average[0] = 0.0; average[1] = 0.0; average[2] = 0.0;
01091     avg = 0;
01092     while (node) {
01093       /* only average if the dot product of the angle between the two
01094          facet normals is greater than the cosine of the threshold
01095          angle -- or, said another way, the angle between the two
01096          facet normals is less than (or equal to) the threshold angle */
01097       dot = _glmDot(&model->facetnorms[3 * T(node->index).findex],
01098                     &model->facetnorms[3 * T(members[i]->index).findex]);
01099       if (dot > cos_angle) {
01100         node->averaged = GL_TRUE;
01101         average[0] += model->facetnorms[3 * T(node->index).findex + 0];
01102         average[1] += model->facetnorms[3 * T(node->index).findex + 1];
01103         average[2] += model->facetnorms[3 * T(node->index).findex + 2];
01104         avg = 1;                        /* we averaged at least one normal! */
01105       } else {
01106         node->averaged = GL_FALSE;
01107       }
01108       node = node->next;
01109     }
01110 
01111     if (avg) {
01112       /* normalize the averaged normal */
01113       _glmNormalize(average);
01114 
01115       /* add the normal to the vertex normals list */
01116       model->normals[3 * numnormals + 0] = average[0];
01117       model->normals[3 * numnormals + 1] = average[1];
01118       model->normals[3 * numnormals + 2] = average[2];
01119       avg = numnormals;
01120       numnormals++;
01121     }
01122 
01123     /* set the normal of this vertex in each triangle it is in */
01124     node = members[i];
01125     while (node) {
01126       if (node->averaged) {
01127         /* if this node was averaged, use the average normal */
01128         if (T(node->index).vindices[0] == i)
01129           T(node->index).nindices[0] = avg;
01130         else if (T(node->index).vindices[1] == i)
01131           T(node->index).nindices[1] = avg;
01132         else if (T(node->index).vindices[2] == i)
01133           T(node->index).nindices[2] = avg;
01134       } else {
01135         /* if this node wasn't averaged, use the facet normal */
01136         model->normals[3 * numnormals + 0] = 
01137           model->facetnorms[3 * T(node->index).findex + 0];
01138         model->normals[3 * numnormals + 1] = 
01139           model->facetnorms[3 * T(node->index).findex + 1];
01140         model->normals[3 * numnormals + 2] = 
01141           model->facetnorms[3 * T(node->index).findex + 2];
01142         if (T(node->index).vindices[0] == i)
01143           T(node->index).nindices[0] = numnormals;
01144         else if (T(node->index).vindices[1] == i)
01145           T(node->index).nindices[1] = numnormals;
01146         else if (T(node->index).vindices[2] == i)
01147           T(node->index).nindices[2] = numnormals;
01148         numnormals++;
01149       }
01150       node = node->next;
01151     }
01152   }
01153   
01154   model->numnormals = numnormals - 1;
01155 
01156   /* free the member information */
01157   for (i = 1; i <= model->numvertices; i++) {
01158     node = members[i];
01159     while (node) {
01160       tail = node;
01161       node = node->next;
01162       free(tail);
01163     }
01164   }
01165   free(members);
01166 
01167   /* pack the normals array (we previously allocated the maximum
01168      number of normals that could possibly be created (numtriangles *
01169      3), so get rid of some of them (usually alot unless none of the
01170      facet normals were averaged)) */
01171   normals = model->normals;
01172   model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1));
01173   for (i = 1; i <= model->numnormals; i++) {
01174     model->normals[3 * i + 0] = normals[3 * i + 0];
01175     model->normals[3 * i + 1] = normals[3 * i + 1];
01176     model->normals[3 * i + 2] = normals[3 * i + 2];
01177   }
01178   free(normals);
01179 
01180   printf("glmVertexNormals(): %d normals generated\n", model->numnormals);
01181 }

GLvoid glmLinearTexture GLMmodel *    model
 

01192 {
01193   GLMgroup *group;
01194   GLfloat dimensions[3];
01195   GLfloat x, y, scalefactor;
01196   GLuint i;
01197   
01198   assert(model);
01199 
01200   if (model->texcoords)
01201     free(model->texcoords);
01202   model->numtexcoords = model->numvertices;
01203   model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1));
01204   
01205   glmDimensions(model, dimensions);
01206   scalefactor = 2.0 / 
01207     _glmAbs(_glmMax(_glmMax(dimensions[0], dimensions[1]), dimensions[2]));
01208 
01209   /* do the calculations */
01210   for(i = 1; i <= model->numvertices; i++) {
01211     x = model->vertices[3 * i + 0] * scalefactor;
01212     y = model->vertices[3 * i + 2] * scalefactor;
01213     model->texcoords[2 * i + 0] = (x + 1.0) / 2.0;
01214     model->texcoords[2 * i + 1] = (y + 1.0) / 2.0;
01215   }
01216   
01217   /* go through and put texture coordinate indices in all the triangles */
01218   group = model->groups;
01219   while(group) {
01220     for(i = 0; i < group->numtriangles; i++) {
01221       T(group->triangles[i]).tindices[0] = T(group->triangles[i]).vindices[0];
01222       T(group->triangles[i]).tindices[1] = T(group->triangles[i]).vindices[1];
01223       T(group->triangles[i]).tindices[2] = T(group->triangles[i]).vindices[2];
01224     }    
01225     group = group->next;
01226   }
01227 
01228 #if 0
01229   printf("glmLinearTexture(): generated %d linear texture coordinates\n",
01230           model->numtexcoords);
01231 #endif
01232 }

GLvoid glmSpheremapTexture GLMmodel *    model
 

01247 {
01248   GLMgroup* group;
01249   GLfloat theta, phi, rho, x, y, z, r;
01250   GLuint i;
01251   
01252   assert(model);
01253   assert(model->normals);
01254 
01255   if (model->texcoords)
01256     free(model->texcoords);
01257   model->numtexcoords = model->numnormals;
01258   model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1));
01259      
01260   /* do the calculations */
01261   for (i = 1; i <= model->numnormals; i++) {
01262     z = model->normals[3 * i + 0];      /* re-arrange for pole distortion */
01263     y = model->normals[3 * i + 1];
01264     x = model->normals[3 * i + 2];
01265     r = sqrt((x * x) + (y * y));
01266     rho = sqrt((r * r) + (z * z));
01267       
01268     if(r == 0.0) {
01269         theta = 0.0;
01270         phi = 0.0;
01271     } else {
01272       if(z == 0.0)
01273         phi = M_PI / 2.0;
01274       else
01275         phi = acos(z / rho);
01276       
01277 #if WE_DONT_NEED_THIS_CODE
01278       if(x == 0.0)
01279         theta = M_PI / 2.0;     /* asin(y / r); */
01280       else
01281         theta = acos(x / r);
01282 #endif
01283       
01284       if(y == 0.0)
01285         theta = M_PI / 2.0;     /* acos(x / r); */
01286       else
01287         theta = asin(y / r) + (M_PI / 2.0);
01288     }
01289     
01290     model->texcoords[2 * i + 0] = theta / M_PI;
01291     model->texcoords[2 * i + 1] = phi / M_PI;
01292   }
01293   
01294   /* go through and put texcoord indices in all the triangles */
01295   group = model->groups;
01296   while(group) {
01297     for (i = 0; i < group->numtriangles; i++) {
01298       T(group->triangles[i]).tindices[0] = T(group->triangles[i]).nindices[0];
01299       T(group->triangles[i]).tindices[1] = T(group->triangles[i]).nindices[1];
01300       T(group->triangles[i]).tindices[2] = T(group->triangles[i]).nindices[2];
01301     }
01302     group = group->next;
01303   }
01304 
01305 #if 0  
01306   printf("glmSpheremapTexture(): generated %d spheremap texture coordinates\n",
01307          model->numtexcoords);
01308 #endif
01309 }

GLvoid glmDelete GLMmodel *    model
 

01317 {
01318   GLMgroup* group;
01319   GLuint i;
01320 
01321   assert(model);
01322 
01323   if (model->pathname)   free(model->pathname);
01324   if (model->mtllibname) free(model->mtllibname);
01325   if (model->vertices)   free(model->vertices);
01326   if (model->normals)    free(model->normals);
01327   if (model->texcoords)  free(model->texcoords);
01328   if (model->facetnorms) free(model->facetnorms);
01329   if (model->triangles)  free(model->triangles);
01330   if (model->materials) {
01331     for (i = 0; i < model->nummaterials; i++)
01332       free(model->materials[i].name);
01333   }
01334   free(model->materials);
01335   while(model->groups) {
01336     group = model->groups;
01337     model->groups = model->groups->next;
01338     free(group->name);
01339     free(group->triangles);
01340     free(group);
01341   }
01342 
01343   free(model);
01344 }

GLMmodel* glmReadOBJ char *    filename
 

01354 {
01355   GLMmodel* model;
01356   FILE*     file;
01357 
01358   /* open the file */
01359   file = fopen(filename, "r");
01360   if (!file) {
01361     fprintf(stderr, "glmReadOBJ() failed: can't open data file \"%s\".\n",
01362             filename);
01363     exit(1);
01364   }
01365 
01366 #if 0
01367   /* announce the model name */
01368   printf("Model: %s\n", filename);
01369 #endif
01370 
01371   /* allocate a new model */
01372   model = (GLMmodel*)malloc(sizeof(GLMmodel));
01373   model->pathname      = stralloc(filename);
01374   model->mtllibname    = NULL;
01375   model->numvertices   = 0;
01376   model->vertices      = NULL;
01377   model->numnormals    = 0;
01378   model->normals       = NULL;
01379   model->numtexcoords  = 0;
01380   model->texcoords     = NULL;
01381   model->numfacetnorms = 0;
01382   model->facetnorms    = NULL;
01383   model->numtriangles  = 0;
01384   model->triangles     = NULL;
01385   model->nummaterials  = 0;
01386   model->materials     = NULL;
01387   model->numgroups     = 0;
01388   model->groups        = NULL;
01389   model->position[0]   = 0.0;
01390   model->position[1]   = 0.0;
01391   model->position[2]   = 0.0;
01392 
01393   /* make a first pass through the file to get a count of the number
01394      of vertices, normals, texcoords & triangles */
01395   _glmFirstPass(model, file);
01396 
01397   /* allocate memory */
01398   model->vertices = (GLfloat*)malloc(sizeof(GLfloat) *
01399                                      3 * (model->numvertices + 1));
01400   model->triangles = (GLMtriangle*)malloc(sizeof(GLMtriangle) *
01401                                           model->numtriangles);
01402   if (model->numnormals) {
01403     model->normals = (GLfloat*)malloc(sizeof(GLfloat) *
01404                                       3 * (model->numnormals + 1));
01405   }
01406   if (model->numtexcoords) {
01407     model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) *
01408                                         2 * (model->numtexcoords + 1));
01409   }
01410 
01411   /* rewind to beginning of file and read in the data this pass */
01412   rewind(file);
01413 
01414   _glmSecondPass(model, file);
01415 
01416   /* close the file */
01417   fclose(file);
01418 
01419   return model;
01420 }

GLvoid glmWriteOBJ GLMmodel *    model,
char *    filename,
GLuint    mode
 

01439 {
01440   GLuint    i;
01441   FILE*     file;
01442   GLMgroup* group;
01443 
01444   assert(model);
01445 
01446   /* do a bit of warning */
01447   if (mode & GLM_FLAT && !model->facetnorms) {
01448     printf("glmWriteOBJ() warning: flat normal output requested "
01449            "with no facet normals defined.\n");
01450     mode &= ~GLM_FLAT;
01451   }
01452   if (mode & GLM_SMOOTH && !model->normals) {
01453     printf("glmWriteOBJ() warning: smooth normal output requested "
01454            "with no normals defined.\n");
01455     mode &= ~GLM_SMOOTH;
01456   }
01457   if (mode & GLM_TEXTURE && !model->texcoords) {
01458     printf("glmWriteOBJ() warning: texture coordinate output requested "
01459            "with no texture coordinates defined.\n");
01460     mode &= ~GLM_TEXTURE;
01461   }
01462   if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
01463     printf("glmWriteOBJ() warning: flat normal output requested "
01464            "and smooth normal output requested (using smooth).\n");
01465     mode &= ~GLM_FLAT;
01466   }
01467 
01468   /* open the file */
01469   file = fopen(filename, "w");
01470   if (!file) {
01471     fprintf(stderr, "glmWriteOBJ() failed: can't open file \"%s\" to write.\n",
01472             filename);
01473     exit(1);
01474   }
01475 
01476   /* spit out a header */
01477   fprintf(file, "#  \n");
01478   fprintf(file, "#  Wavefront OBJ generated by GLM library\n");
01479   fprintf(file, "#  \n");
01480   fprintf(file, "#  GLM library copyright (C) 1997 by Nate Robins\n");
01481   fprintf(file, "#  email: ndr@pobox.com\n");
01482   fprintf(file, "#  www:   http://www.pobox.com/~ndr\n");
01483   fprintf(file, "#  \n");
01484 
01485   if (mode & GLM_MATERIAL && model->mtllibname) {
01486     fprintf(file, "\nmtllib %s\n\n", model->mtllibname);
01487     _glmWriteMTL(model, filename, model->mtllibname);
01488   }
01489 
01490   /* spit out the vertices */
01491   fprintf(file, "\n");
01492   fprintf(file, "# %d vertices\n", model->numvertices);
01493   for (i = 1; i <= model->numvertices; i++) {
01494     fprintf(file, "v %f %f %f\n", 
01495             model->vertices[3 * i + 0],
01496             model->vertices[3 * i + 1],
01497             model->vertices[3 * i + 2]);
01498   }
01499 
01500   /* spit out the smooth/flat normals */
01501   if (mode & GLM_SMOOTH) {
01502     fprintf(file, "\n");
01503     fprintf(file, "# %d normals\n", model->numnormals);
01504     for (i = 1; i <= model->numnormals; i++) {
01505       fprintf(file, "vn %f %f %f\n", 
01506               model->normals[3 * i + 0],
01507               model->normals[3 * i + 1],
01508               model->normals[3 * i + 2]);
01509     }
01510   } else if (mode & GLM_FLAT) {
01511     fprintf(file, "\n");
01512     fprintf(file, "# %d normals\n", model->numfacetnorms);
01513     for (i = 1; i <= model->numnormals; i++) {
01514       fprintf(file, "vn %f %f %f\n", 
01515               model->facetnorms[3 * i + 0],
01516               model->facetnorms[3 * i + 1],
01517               model->facetnorms[3 * i + 2]);
01518     }
01519   }
01520 
01521   /* spit out the texture coordinates */
01522   if (mode & GLM_TEXTURE) {
01523     fprintf(file, "\n");
01524     fprintf(file, "# %d texcoords\n", model->numtexcoords);
01525     for (i = 1; i <= model->numtexcoords; i++) {
01526       fprintf(file, "vt %f %f\n", 
01527               model->texcoords[2 * i + 0],
01528               model->texcoords[2 * i + 1]);
01529     }
01530   }
01531 
01532   fprintf(file, "\n");
01533   fprintf(file, "# %d groups\n", model->numgroups);
01534   fprintf(file, "# %d faces (triangles)\n", model->numtriangles);
01535   fprintf(file, "\n");
01536 
01537   group = model->groups;
01538   while(group) {
01539     fprintf(file, "g %s\n", group->name);
01540     if (mode & GLM_MATERIAL)
01541       fprintf(file, "usemtl %s\n", model->materials[group->material].name);
01542     for (i = 0; i < group->numtriangles; i++) {
01543       if (mode & GLM_SMOOTH && mode & GLM_TEXTURE) {
01544         fprintf(file, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
01545                 T(group->triangles[i]).vindices[0], 
01546                 T(group->triangles[i]).nindices[0], 
01547                 T(group->triangles[i]).tindices[0],
01548                 T(group->triangles[i]).vindices[1],
01549                 T(group->triangles[i]).nindices[1],
01550                 T(group->triangles[i]).tindices[1],
01551                 T(group->triangles[i]).vindices[2],
01552                 T(group->triangles[i]).nindices[2],
01553                 T(group->triangles[i]).tindices[2]);
01554       } else if (mode & GLM_FLAT && mode & GLM_TEXTURE) {
01555         fprintf(file, "f %d/%d %d/%d %d/%d\n",
01556                 T(group->triangles[i]).vindices[0],
01557                 T(group->triangles[i]).findex,
01558                 T(group->triangles[i]).vindices[1],
01559                 T(group->triangles[i]).findex,
01560                 T(group->triangles[i]).vindices[2],
01561                 T(group->triangles[i]).findex);
01562       } else if (mode & GLM_TEXTURE) {
01563         fprintf(file, "f %d/%d %d/%d %d/%d\n",
01564                 T(group->triangles[i]).vindices[0],
01565                 T(group->triangles[i]).tindices[0],
01566                 T(group->triangles[i]).vindices[1],
01567                 T(group->triangles[i]).tindices[1],
01568                 T(group->triangles[i]).vindices[2],
01569                 T(group->triangles[i]).tindices[2]);
01570       } else if (mode & GLM_SMOOTH) {
01571         fprintf(file, "f %d//%d %d//%d %d//%d\n",
01572                 T(group->triangles[i]).vindices[0],
01573                 T(group->triangles[i]).nindices[0],
01574                 T(group->triangles[i]).vindices[1],
01575                 T(group->triangles[i]).nindices[1],
01576                 T(group->triangles[i]).vindices[2], 
01577                 T(group->triangles[i]).nindices[2]);
01578       } else if (mode & GLM_FLAT) {
01579         fprintf(file, "f %d//%d %d//%d %d//%d\n",
01580                 T(group->triangles[i]).vindices[0], 
01581                 T(group->triangles[i]).findex,
01582                 T(group->triangles[i]).vindices[1],
01583                 T(group->triangles[i]).findex,
01584                 T(group->triangles[i]).vindices[2],
01585                 T(group->triangles[i]).findex);
01586       } else {
01587         fprintf(file, "f %d %d %d\n",
01588                 T(group->triangles[i]).vindices[0],
01589                 T(group->triangles[i]).vindices[1],
01590                 T(group->triangles[i]).vindices[2]);
01591       }
01592     }
01593     fprintf(file, "\n");
01594     group = group->next;
01595   }
01596 
01597   fclose(file);
01598 }

GLvoid glmDraw GLMmodel *    model,
GLuint    mode
 

01616 {
01617   GLuint i;
01618   GLMgroup* group;
01619 
01620   assert(model);
01621   assert(model->vertices);
01622 
01623   /* do a bit of warning */
01624   if (mode & GLM_FLAT && !model->facetnorms) {
01625     printf("glmDraw() warning: flat render mode requested "
01626            "with no facet normals defined.\n");
01627     mode &= ~GLM_FLAT;
01628   }
01629   if (mode & GLM_SMOOTH && !model->normals) {
01630     printf("glmDraw() warning: smooth render mode requested "
01631            "with no normals defined.\n");
01632     mode &= ~GLM_SMOOTH;
01633   }
01634   if (mode & GLM_TEXTURE && !model->texcoords) {
01635     printf("glmDraw() warning: texture render mode requested "
01636            "with no texture coordinates defined.\n");
01637     mode &= ~GLM_TEXTURE;
01638   }
01639   if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
01640     printf("glmDraw() warning: flat render mode requested "
01641            "and smooth render mode requested (using smooth).\n");
01642     mode &= ~GLM_FLAT;
01643   }
01644   if (mode & GLM_COLOR && !model->materials) {
01645     printf("glmDraw() warning: color render mode requested "
01646            "with no materials defined.\n");
01647     mode &= ~GLM_COLOR;
01648   }
01649   if (mode & GLM_MATERIAL && !model->materials) {
01650     printf("glmDraw() warning: material render mode requested "
01651            "with no materials defined.\n");
01652     mode &= ~GLM_MATERIAL;
01653   }
01654   if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
01655     printf("glmDraw() warning: color and material render mode requested "
01656            "using only material mode\n");
01657     mode &= ~GLM_COLOR;
01658   }
01659   if (mode & GLM_COLOR)
01660     glEnable(GL_COLOR_MATERIAL);
01661   if (mode & GLM_MATERIAL)
01662     glDisable(GL_COLOR_MATERIAL);
01663 
01664   glPushMatrix();
01665   glTranslatef(model->position[0], model->position[1], model->position[2]);
01666 
01667   glBegin(GL_TRIANGLES);
01668   group = model->groups;
01669   while (group) {
01670     if (mode & GLM_MATERIAL) {
01671       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, 
01672                    model->materials[group->material].ambient);
01673       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
01674                    model->materials[group->material].diffuse);
01675       glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, 
01676                    model->materials[group->material].specular);
01677        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 
01678                   model->materials[group->material].shininess);
01679     }
01680 
01681     if (mode & GLM_COLOR) {
01682       glColor3fv(model->materials[group->material].diffuse);
01683     }
01684 
01685     for (i = 0; i < group->numtriangles; i++) {
01686       if (mode & GLM_FLAT)
01687         glNormal3fv(&model->facetnorms[3 * T(group->triangles[i]).findex]);
01688       
01689       if (mode & GLM_SMOOTH)
01690         glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[0]]);
01691       if (mode & GLM_TEXTURE)
01692         glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[0]]);
01693       glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[0]]);
01694 #if 0
01695       printf("%f %f %f\n", 
01696              model->vertices[3 * T(group->triangles[i]).vindices[0] + X],
01697              model->vertices[3 * T(group->triangles[i]).vindices[0] + Y],
01698              model->vertices[3 * T(group->triangles[i]).vindices[0] + Z]);
01699 #endif
01700       
01701       if (mode & GLM_SMOOTH)
01702         glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[1]]);
01703       if (mode & GLM_TEXTURE)
01704         glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[1]]);
01705       glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[1]]);
01706 #if 0
01707       printf("%f %f %f\n", 
01708              model->vertices[3 * T(group->triangles[i]).vindices[1] + X],
01709              model->vertices[3 * T(group->triangles[i]).vindices[1] + Y],
01710              model->vertices[3 * T(group->triangles[i]).vindices[1] + Z]);
01711 #endif
01712       
01713       if (mode & GLM_SMOOTH)
01714         glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[2]]);
01715       if (mode & GLM_TEXTURE)
01716         glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[2]]);
01717       glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[2]]);
01718 #if 0
01719       printf("%f %f %f\n", 
01720              model->vertices[3 * T(group->triangles[i]).vindices[2] + X],
01721              model->vertices[3 * T(group->triangles[i]).vindices[2] + Y],
01722              model->vertices[3 * T(group->triangles[i]).vindices[2] + Z]);
01723 #endif
01724       
01725     }
01726     
01727     group = group->next;
01728   }
01729   glEnd();
01730 
01731   glPopMatrix();
01732 }

GLuint glmList GLMmodel *    model,
GLuint    mode
 

01750 {
01751   GLuint list;
01752 
01753   list = glGenLists(1);
01754   glNewList(list, GL_COMPILE);
01755   glmDraw(model, mode);
01756   glEndList();
01757 
01758   return list;
01759 }

GLvoid glmWeld GLMmodel *    model,
GLfloat    epsilon
 

01771 {
01772   GLfloat* vectors;
01773   GLfloat* copies;
01774   GLuint   numvectors;
01775   GLuint   i;
01776 
01777   /* vertices */
01778   numvectors = model->numvertices;
01779   vectors    = model->vertices;
01780   copies = _glmWeldVectors(vectors, &numvectors, epsilon);
01781 
01782   printf("glmWeld(): %d redundant vertices.\n", 
01783          model->numvertices - numvectors - 1);
01784 
01785   for (i = 0; i < model->numtriangles; i++) {
01786     T(i).vindices[0] = (GLuint)vectors[3 * T(i).vindices[0] + 0];
01787     T(i).vindices[1] = (GLuint)vectors[3 * T(i).vindices[1] + 0];
01788     T(i).vindices[2] = (GLuint)vectors[3 * T(i).vindices[2] + 0];
01789   }
01790 
01791   /* free space for old vertices */
01792   free(vectors);
01793 
01794   /* allocate space for the new vertices */
01795   model->numvertices = numvectors;
01796   model->vertices = (GLfloat*)malloc(sizeof(GLfloat) * 
01797                                      3 * (model->numvertices + 1));
01798 
01799   /* copy the optimized vertices into the actual vertex list */
01800   for (i = 1; i <= model->numvertices; i++) {
01801     model->vertices[3 * i + 0] = copies[3 * i + 0];
01802     model->vertices[3 * i + 1] = copies[3 * i + 1];
01803     model->vertices[3 * i + 2] = copies[3 * i + 2];
01804   }
01805 
01806   free(copies);
01807 }


Generated on Sat Jul 19 04:01:57 2003 for SIMEX by doxygen1.2.18