00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <math.h>
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <assert.h>
00020 #include <esg/parser/glm.h>
00021
00022
00023 #define T(x) (model->triangles[(x)])
00024
00025
00026
00027
00028 typedef struct _GLMnode {
00029 GLuint index;
00030 GLboolean averaged;
00031 struct _GLMnode* next;
00032 } GLMnode;
00033
00034
00035
00036 static GLfloat
00037 glmMax(GLfloat a, GLfloat b)
00038 {
00039 if (b > a)
00040 return b;
00041 return a;
00042 }
00043
00044
00045 static GLfloat
00046 glmAbs(GLfloat f)
00047 {
00048 if (f < 0)
00049 return -f;
00050 return f;
00051 }
00052
00053
00054
00055
00056
00057
00058 static GLfloat
00059 glmDot(GLfloat* u, GLfloat* v)
00060 {
00061 assert(u); assert(v);
00062
00063 return u[0]*v[0] + u[1]*v[1] + u[2]*v[2];
00064 }
00065
00066
00067
00068
00069
00070
00071
00072 static GLvoid
00073 glmCross(GLfloat* u, GLfloat* v, GLfloat* n)
00074 {
00075 assert(u); assert(v); assert(n);
00076
00077 n[0] = u[1]*v[2] - u[2]*v[1];
00078 n[1] = u[2]*v[0] - u[0]*v[2];
00079 n[2] = u[0]*v[1] - u[1]*v[0];
00080 }
00081
00082
00083
00084
00085
00086 static GLvoid
00087 glmNormalize(GLfloat* v)
00088 {
00089 GLfloat l;
00090
00091 assert(v);
00092
00093 l = (GLfloat)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00094 v[0] /= l;
00095 v[1] /= l;
00096 v[2] /= l;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106 static GLboolean
00107 glmEqual(GLfloat* u, GLfloat* v, GLfloat epsilon)
00108 {
00109 if (glmAbs(u[0] - v[0]) < epsilon &&
00110 glmAbs(u[1] - v[1]) < epsilon &&
00111 glmAbs(u[2] - v[2]) < epsilon)
00112 {
00113 return GL_TRUE;
00114 }
00115 return GL_FALSE;
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 GLfloat*
00127 glmWeldVectors(GLfloat* vectors, GLuint* numvectors, GLfloat epsilon)
00128 {
00129 GLfloat* copies;
00130 GLuint copied;
00131 GLuint i, j;
00132
00133 copies = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (*numvectors + 1));
00134 memcpy(copies, vectors, (sizeof(GLfloat) * 3 * (*numvectors + 1)));
00135
00136 copied = 1;
00137 for (i = 1; i <= *numvectors; i++) {
00138 for (j = 1; j <= copied; j++) {
00139 if (glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {
00140 goto duplicate;
00141 }
00142 }
00143
00144
00145 copies[3 * copied + 0] = vectors[3 * i + 0];
00146 copies[3 * copied + 1] = vectors[3 * i + 1];
00147 copies[3 * copied + 2] = vectors[3 * i + 2];
00148 j = copied;
00149 copied++;
00150
00151 duplicate:
00152
00153
00154 vectors[3 * i + 0] = (GLfloat)j;
00155 }
00156
00157 *numvectors = copied-1;
00158 return copies;
00159 }
00160
00161
00162
00163 GLMgroup*
00164 glmFindGroup(GLMmodel* model, char* name)
00165 {
00166 GLMgroup* group;
00167
00168 assert(model);
00169
00170 group = model->groups;
00171 while(group) {
00172 if (!strcmp(name, group->name))
00173 break;
00174 group = group->next;
00175 }
00176
00177 return group;
00178 }
00179
00180
00181
00182 GLMgroup*
00183 glmAddGroup(GLMmodel* model, char* name)
00184 {
00185 GLMgroup* group;
00186
00187 group = glmFindGroup(model, name);
00188 if (!group) {
00189 group = (GLMgroup*)malloc(sizeof(GLMgroup));
00190 group->name = strdup(name);
00191 group->material = 0;
00192 group->numtriangles = 0;
00193 group->triangles = NULL;
00194 group->next = model->groups;
00195 model->groups = group;
00196 model->numgroups++;
00197 }
00198
00199 return group;
00200 }
00201
00202
00203
00204 GLuint
00205 glmFindMaterial(GLMmodel* model, char* name)
00206 {
00207 GLuint i;
00208
00209
00210
00211 for (i = 0; i < model->nummaterials; i++) {
00212 if (!strcmp(model->materials[i].name, name))
00213 goto found;
00214 }
00215
00216
00217
00218 printf("glmFindMaterial(): can't find material \"%s\".\n", name);
00219 i = 0;
00220
00221 found:
00222 return i;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232 static char*
00233 glmDirName(char* path)
00234 {
00235 char* dir;
00236 char* s;
00237
00238 dir = strdup(path);
00239
00240 s = strrchr(dir, '/');
00241 if (s)
00242 s[1] = '\0';
00243 else
00244 dir[0] = '\0';
00245
00246 return dir;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255 static GLvoid
00256 glmReadMTL(GLMmodel* model, char* name)
00257 {
00258 FILE* file;
00259 char* dir;
00260 char* filename;
00261 char buf[128];
00262 GLuint nummaterials, i;
00263
00264 dir = glmDirName(model->pathname);
00265 filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1));
00266 strcpy(filename, dir);
00267 strcat(filename, name);
00268 free(dir);
00269
00270 file = fopen(filename, "r");
00271 if (!file) {
00272 fprintf(stderr, "glmReadMTL() failed: can't open material file \"%s\".\n",
00273 filename);
00274 exit(1);
00275 }
00276 free(filename);
00277
00278
00279 nummaterials = 1;
00280 while(fscanf(file, "%s", buf) != EOF) {
00281 switch(buf[0]) {
00282 case '#':
00283
00284 fgets(buf, sizeof(buf), file);
00285 break;
00286 case 'n':
00287 fgets(buf, sizeof(buf), file);
00288 nummaterials++;
00289 sscanf(buf, "%s %s", buf, buf);
00290 break;
00291 default:
00292
00293 fgets(buf, sizeof(buf), file);
00294 break;
00295 }
00296 }
00297
00298 rewind(file);
00299
00300 model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * nummaterials);
00301 model->nummaterials = nummaterials;
00302
00303
00304 for (i = 0; i < nummaterials; i++) {
00305 model->materials[i].name = NULL;
00306 model->materials[i].shininess = 65.0;
00307 model->materials[i].diffuse[0] = 0.8;
00308 model->materials[i].diffuse[1] = 0.8;
00309 model->materials[i].diffuse[2] = 0.8;
00310 model->materials[i].diffuse[3] = 1.0;
00311 model->materials[i].ambient[0] = 0.2;
00312 model->materials[i].ambient[1] = 0.2;
00313 model->materials[i].ambient[2] = 0.2;
00314 model->materials[i].ambient[3] = 1.0;
00315 model->materials[i].specular[0] = 0.0;
00316 model->materials[i].specular[1] = 0.0;
00317 model->materials[i].specular[2] = 0.0;
00318 model->materials[i].specular[3] = 1.0;
00319 }
00320 model->materials[0].name = strdup("default");
00321
00322
00323 nummaterials = 0;
00324 while(fscanf(file, "%s", buf) != EOF) {
00325 switch(buf[0]) {
00326 case '#':
00327
00328 fgets(buf, sizeof(buf), file);
00329 break;
00330 case 'n':
00331 fgets(buf, sizeof(buf), file);
00332 sscanf(buf, "%s %s", buf, buf);
00333 nummaterials++;
00334 model->materials[nummaterials].name = strdup(buf);
00335 break;
00336 case 'N':
00337 fscanf(file, "%f", &model->materials[nummaterials].shininess);
00338
00339 model->materials[nummaterials].shininess /= 1000.0;
00340 model->materials[nummaterials].shininess *= 128.0;
00341 break;
00342 case 'K':
00343 switch(buf[1]) {
00344 case 'd':
00345 fscanf(file, "%f %f %f",
00346 &model->materials[nummaterials].diffuse[0],
00347 &model->materials[nummaterials].diffuse[1],
00348 &model->materials[nummaterials].diffuse[2]);
00349 break;
00350 case 's':
00351 fscanf(file, "%f %f %f",
00352 &model->materials[nummaterials].specular[0],
00353 &model->materials[nummaterials].specular[1],
00354 &model->materials[nummaterials].specular[2]);
00355 break;
00356 case 'a':
00357 fscanf(file, "%f %f %f",
00358 &model->materials[nummaterials].ambient[0],
00359 &model->materials[nummaterials].ambient[1],
00360 &model->materials[nummaterials].ambient[2]);
00361 break;
00362 default:
00363
00364 fgets(buf, sizeof(buf), file);
00365 break;
00366 }
00367 break;
00368 default:
00369
00370 fgets(buf, sizeof(buf), file);
00371 break;
00372 }
00373 }
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 static GLvoid
00383 glmWriteMTL(GLMmodel* model, char* modelpath, char* mtllibname)
00384 {
00385 FILE* file;
00386 char* dir;
00387 char* filename;
00388 GLMmaterial* material;
00389 GLuint i;
00390
00391 dir = glmDirName(modelpath);
00392 filename = (char*)malloc(sizeof(char) * (strlen(dir)+strlen(mtllibname)));
00393 strcpy(filename, dir);
00394 strcat(filename, mtllibname);
00395 free(dir);
00396
00397
00398 file = fopen(filename, "w");
00399 if (!file) {
00400 fprintf(stderr, "glmWriteMTL() failed: can't open file \"%s\".\n",
00401 filename);
00402 exit(1);
00403 }
00404 free(filename);
00405
00406
00407 fprintf(file, "# \n");
00408 fprintf(file, "# Wavefront MTL generated by GLM library\n");
00409 fprintf(file, "# \n");
00410 fprintf(file, "# GLM library\n");
00411 fprintf(file, "# Nate Robins\n");
00412 fprintf(file, "# ndr@pobox.com\n");
00413 fprintf(file, "# http://www.pobox.com/~ndr\n");
00414 fprintf(file, "# \n\n");
00415
00416 for (i = 0; i < model->nummaterials; i++) {
00417 material = &model->materials[i];
00418 fprintf(file, "newmtl %s\n", material->name);
00419 fprintf(file, "Ka %f %f %f\n",
00420 material->ambient[0], material->ambient[1], material->ambient[2]);
00421 fprintf(file, "Kd %f %f %f\n",
00422 material->diffuse[0], material->diffuse[1], material->diffuse[2]);
00423 fprintf(file, "Ks %f %f %f\n",
00424 material->specular[0],material->specular[1],material->specular[2]);
00425 fprintf(file, "Ns %f\n", material->shininess / 128.0 * 1000.0);
00426 fprintf(file, "\n");
00427 }
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437 static GLvoid
00438 glmFirstPass(GLMmodel* model, FILE* file)
00439 {
00440 GLuint numvertices;
00441 GLuint numnormals;
00442 GLuint numtexcoords;
00443 GLuint numtriangles;
00444 GLMgroup* group;
00445 unsigned v, n, t;
00446 char buf[128];
00447
00448
00449 group = glmAddGroup(model, "default");
00450
00451 numvertices = numnormals = numtexcoords = numtriangles = 0;
00452 while(fscanf(file, "%s", buf) != EOF) {
00453 switch(buf[0]) {
00454 case '#':
00455
00456 fgets(buf, sizeof(buf), file);
00457 break;
00458 case 'v':
00459 switch(buf[1]) {
00460 case '\0':
00461
00462 fgets(buf, sizeof(buf), file);
00463 numvertices++;
00464 break;
00465 case 'n':
00466
00467 fgets(buf, sizeof(buf), file);
00468 numnormals++;
00469 break;
00470 case 't':
00471
00472 fgets(buf, sizeof(buf), file);
00473 numtexcoords++;
00474 break;
00475 default:
00476 printf("glmFirstPass(): Unknown token \"%s\".\n", buf);
00477 exit(1);
00478 break;
00479 }
00480 break;
00481 case 'm':
00482 fgets(buf, sizeof(buf), file);
00483 sscanf(buf, "%s %s", buf, buf);
00484 model->mtllibname = strdup(buf);
00485 glmReadMTL(model, buf);
00486 break;
00487 case 'u':
00488
00489 fgets(buf, sizeof(buf), file);
00490 break;
00491 case 'g':
00492
00493 fgets(buf, sizeof(buf), file);
00494 #if SINGLE_STRING_GROUP_NAMES
00495 sscanf(buf, "%s", buf);
00496 #else
00497 buf[strlen(buf)-1] = '\0';
00498 #endif
00499 group = glmAddGroup(model, buf);
00500 break;
00501 case 'f':
00502 v = n = t = 0;
00503 fscanf(file, "%s", buf);
00504
00505 if (strstr(buf, "//")) {
00506
00507 sscanf(buf, "%d//%d", &v, &n);
00508 fscanf(file, "%d//%d", &v, &n);
00509 fscanf(file, "%d//%d", &v, &n);
00510 numtriangles++;
00511 group->numtriangles++;
00512 while(fscanf(file, "%d//%d", &v, &n) > 0) {
00513 numtriangles++;
00514 group->numtriangles++;
00515 }
00516 } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
00517
00518 fscanf(file, "%d/%d/%d", &v, &t, &n);
00519 fscanf(file, "%d/%d/%d", &v, &t, &n);
00520 numtriangles++;
00521 group->numtriangles++;
00522 while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
00523 numtriangles++;
00524 group->numtriangles++;
00525 }
00526 } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
00527
00528 fscanf(file, "%d/%d", &v, &t);
00529 fscanf(file, "%d/%d", &v, &t);
00530 numtriangles++;
00531 group->numtriangles++;
00532 while(fscanf(file, "%d/%d", &v, &t) > 0) {
00533 numtriangles++;
00534 group->numtriangles++;
00535 }
00536 } else {
00537
00538 fscanf(file, "%d", &v);
00539 fscanf(file, "%d", &v);
00540 numtriangles++;
00541 group->numtriangles++;
00542 while(fscanf(file, "%d", &v) > 0) {
00543 numtriangles++;
00544 group->numtriangles++;
00545 }
00546 }
00547 break;
00548
00549 default:
00550
00551 fgets(buf, sizeof(buf), file);
00552 break;
00553 }
00554 }
00555
00556
00557 model->numvertices = numvertices;
00558 model->numnormals = numnormals;
00559 model->numtexcoords = numtexcoords;
00560 model->numtriangles = numtriangles;
00561
00562
00563 group = model->groups;
00564 while(group) {
00565 group->triangles = (GLuint*)malloc(sizeof(GLuint) * group->numtriangles);
00566 group->numtriangles = 0;
00567 group = group->next;
00568 }
00569 }
00570
00571
00572
00573
00574
00575
00576
00577 static GLvoid
00578 glmSecondPass(GLMmodel* model, FILE* file)
00579 {
00580 GLuint numvertices;
00581 GLuint numnormals;
00582 GLuint numtexcoords;
00583 GLuint numtriangles;
00584 GLfloat* vertices;
00585 GLfloat* normals;
00586 GLfloat* texcoords;
00587 GLMgroup* group;
00588 GLuint material;
00589 GLuint v, n, t;
00590 char buf[128];
00591
00592
00593 vertices = model->vertices;
00594 normals = model->normals;
00595 texcoords = model->texcoords;
00596 group = model->groups;
00597
00598
00599
00600 numvertices = numnormals = numtexcoords = 1;
00601 numtriangles = 0;
00602 material = 0;
00603 while(fscanf(file, "%s", buf) != EOF) {
00604 switch(buf[0]) {
00605 case '#':
00606
00607 fgets(buf, sizeof(buf), file);
00608 break;
00609 case 'v':
00610 switch(buf[1]) {
00611 case '\0':
00612 fscanf(file, "%f %f %f",
00613 &vertices[3 * numvertices + 0],
00614 &vertices[3 * numvertices + 1],
00615 &vertices[3 * numvertices + 2]);
00616 numvertices++;
00617 break;
00618 case 'n':
00619 fscanf(file, "%f %f %f",
00620 &normals[3 * numnormals + 0],
00621 &normals[3 * numnormals + 1],
00622 &normals[3 * numnormals + 2]);
00623 numnormals++;
00624 break;
00625 case 't':
00626 fscanf(file, "%f %f",
00627 &texcoords[2 * numtexcoords + 0],
00628 &texcoords[2 * numtexcoords + 1]);
00629 numtexcoords++;
00630 break;
00631 }
00632 break;
00633 case 'u':
00634 fgets(buf, sizeof(buf), file);
00635 sscanf(buf, "%s %s", buf, buf);
00636 group->material = material = glmFindMaterial(model, buf);
00637 break;
00638 case 'g':
00639
00640 fgets(buf, sizeof(buf), file);
00641 #if SINGLE_STRING_GROUP_NAMES
00642 sscanf(buf, "%s", buf);
00643 #else
00644 buf[strlen(buf)-1] = '\0';
00645 #endif
00646 group = glmFindGroup(model, buf);
00647 group->material = material;
00648 break;
00649 case 'f':
00650 v = n = t = 0;
00651 fscanf(file, "%s", buf);
00652
00653 if (strstr(buf, "//")) {
00654
00655 sscanf(buf, "%d//%d", &v, &n);
00656 T(numtriangles).vindices[0] = v;
00657 T(numtriangles).nindices[0] = n;
00658 fscanf(file, "%d//%d", &v, &n);
00659 T(numtriangles).vindices[1] = v;
00660 T(numtriangles).nindices[1] = n;
00661 fscanf(file, "%d//%d", &v, &n);
00662 T(numtriangles).vindices[2] = v;
00663 T(numtriangles).nindices[2] = n;
00664 group->triangles[group->numtriangles++] = numtriangles;
00665 numtriangles++;
00666 while(fscanf(file, "%d//%d", &v, &n) > 0) {
00667 T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
00668 T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
00669 T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
00670 T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
00671 T(numtriangles).vindices[2] = v;
00672 T(numtriangles).nindices[2] = n;
00673 group->triangles[group->numtriangles++] = numtriangles;
00674 numtriangles++;
00675 }
00676 } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
00677
00678 T(numtriangles).vindices[0] = v;
00679 T(numtriangles).tindices[0] = t;
00680 T(numtriangles).nindices[0] = n;
00681 fscanf(file, "%d/%d/%d", &v, &t, &n);
00682 T(numtriangles).vindices[1] = v;
00683 T(numtriangles).tindices[1] = t;
00684 T(numtriangles).nindices[1] = n;
00685 fscanf(file, "%d/%d/%d", &v, &t, &n);
00686 T(numtriangles).vindices[2] = v;
00687 T(numtriangles).tindices[2] = t;
00688 T(numtriangles).nindices[2] = n;
00689 group->triangles[group->numtriangles++] = numtriangles;
00690 numtriangles++;
00691 while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
00692 T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
00693 T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
00694 T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
00695 T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
00696 T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
00697 T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
00698 T(numtriangles).vindices[2] = v;
00699 T(numtriangles).tindices[2] = t;
00700 T(numtriangles).nindices[2] = n;
00701 group->triangles[group->numtriangles++] = numtriangles;
00702 numtriangles++;
00703 }
00704 } else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
00705
00706 T(numtriangles).vindices[0] = v;
00707 T(numtriangles).tindices[0] = t;
00708 fscanf(file, "%d/%d", &v, &t);
00709 T(numtriangles).vindices[1] = v;
00710 T(numtriangles).tindices[1] = t;
00711 fscanf(file, "%d/%d", &v, &t);
00712 T(numtriangles).vindices[2] = v;
00713 T(numtriangles).tindices[2] = t;
00714 group->triangles[group->numtriangles++] = numtriangles;
00715 numtriangles++;
00716 while(fscanf(file, "%d/%d", &v, &t) > 0) {
00717 T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
00718 T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
00719 T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
00720 T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
00721 T(numtriangles).vindices[2] = v;
00722 T(numtriangles).tindices[2] = t;
00723 group->triangles[group->numtriangles++] = numtriangles;
00724 numtriangles++;
00725 }
00726 } else {
00727
00728 sscanf(buf, "%d", &v);
00729 T(numtriangles).vindices[0] = v;
00730 fscanf(file, "%d", &v);
00731 T(numtriangles).vindices[1] = v;
00732 fscanf(file, "%d", &v);
00733 T(numtriangles).vindices[2] = v;
00734 group->triangles[group->numtriangles++] = numtriangles;
00735 numtriangles++;
00736 while(fscanf(file, "%d", &v) > 0) {
00737 T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
00738 T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
00739 T(numtriangles).vindices[2] = v;
00740 group->triangles[group->numtriangles++] = numtriangles;
00741 numtriangles++;
00742 }
00743 }
00744 break;
00745
00746 default:
00747
00748 fgets(buf, sizeof(buf), file);
00749 break;
00750 }
00751 }
00752
00753 #if 0
00754
00755 printf(" Memory: %d bytes\n",
00756 numvertices * 3*sizeof(GLfloat) +
00757 numnormals * 3*sizeof(GLfloat) * (numnormals ? 1 : 0) +
00758 numtexcoords * 3*sizeof(GLfloat) * (numtexcoords ? 1 : 0) +
00759 numtriangles * sizeof(GLMtriangle));
00760 #endif
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 GLfloat
00774 glmUnitize(GLMmodel* model)
00775 {
00776 GLuint i;
00777 GLfloat maxx, minx, maxy, miny, maxz, minz;
00778 GLfloat cx, cy, cz, w, h, d;
00779 GLfloat scale;
00780
00781 assert(model);
00782 assert(model->vertices);
00783
00784
00785 maxx = minx = model->vertices[3 + 0];
00786 maxy = miny = model->vertices[3 + 1];
00787 maxz = minz = model->vertices[3 + 2];
00788 for (i = 1; i <= model->numvertices; i++) {
00789 if (maxx < model->vertices[3 * i + 0])
00790 maxx = model->vertices[3 * i + 0];
00791 if (minx > model->vertices[3 * i + 0])
00792 minx = model->vertices[3 * i + 0];
00793
00794 if (maxy < model->vertices[3 * i + 1])
00795 maxy = model->vertices[3 * i + 1];
00796 if (miny > model->vertices[3 * i + 1])
00797 miny = model->vertices[3 * i + 1];
00798
00799 if (maxz < model->vertices[3 * i + 2])
00800 maxz = model->vertices[3 * i + 2];
00801 if (minz > model->vertices[3 * i + 2])
00802 minz = model->vertices[3 * i + 2];
00803 }
00804
00805
00806 w = glmAbs(maxx) + glmAbs(minx);
00807 h = glmAbs(maxy) + glmAbs(miny);
00808 d = glmAbs(maxz) + glmAbs(minz);
00809
00810
00811 cx = (maxx + minx) / 2.0;
00812 cy = (maxy + miny) / 2.0;
00813 cz = (maxz + minz) / 2.0;
00814
00815
00816 scale = 2.0 / glmMax(glmMax(w, h), d);
00817
00818
00819 for (i = 1; i <= model->numvertices; i++) {
00820 model->vertices[3 * i + 0] -= cx;
00821 model->vertices[3 * i + 1] -= cy;
00822 model->vertices[3 * i + 2] -= cz;
00823 model->vertices[3 * i + 0] *= scale;
00824 model->vertices[3 * i + 1] *= scale;
00825 model->vertices[3 * i + 2] *= scale;
00826 }
00827
00828 return scale;
00829 }
00830
00831
00832
00833
00834
00835
00836
00837 GLvoid
00838 glmDimensions(GLMmodel* model, GLfloat* dimensions)
00839 {
00840 GLuint i;
00841 GLfloat maxx, minx, maxy, miny, maxz, minz;
00842
00843 assert(model);
00844 assert(model->vertices);
00845 assert(dimensions);
00846
00847
00848 maxx = minx = model->vertices[3 + 0];
00849 maxy = miny = model->vertices[3 + 1];
00850 maxz = minz = model->vertices[3 + 2];
00851 for (i = 1; i <= model->numvertices; i++) {
00852 if (maxx < model->vertices[3 * i + 0])
00853 maxx = model->vertices[3 * i + 0];
00854 if (minx > model->vertices[3 * i + 0])
00855 minx = model->vertices[3 * i + 0];
00856
00857 if (maxy < model->vertices[3 * i + 1])
00858 maxy = model->vertices[3 * i + 1];
00859 if (miny > model->vertices[3 * i + 1])
00860 miny = model->vertices[3 * i + 1];
00861
00862 if (maxz < model->vertices[3 * i + 2])
00863 maxz = model->vertices[3 * i + 2];
00864 if (minz > model->vertices[3 * i + 2])
00865 minz = model->vertices[3 * i + 2];
00866 }
00867
00868
00869 dimensions[0] = glmAbs(maxx) + glmAbs(minx);
00870 dimensions[1] = glmAbs(maxy) + glmAbs(miny);
00871 dimensions[2] = glmAbs(maxz) + glmAbs(minz);
00872 }
00873
00874
00875
00876
00877
00878
00879 GLvoid
00880 glmScale(GLMmodel* model, GLfloat scale)
00881 {
00882 GLuint i;
00883
00884 for (i = 1; i <= model->numvertices; i++) {
00885 model->vertices[3 * i + 0] *= scale;
00886 model->vertices[3 * i + 1] *= scale;
00887 model->vertices[3 * i + 2] *= scale;
00888 }
00889 }
00890
00891
00892
00893
00894
00895
00896
00897 GLvoid
00898 glmReverseWinding(GLMmodel* model)
00899 {
00900 GLuint i, swap;
00901
00902 assert(model);
00903
00904 for (i = 0; i < model->numtriangles; i++) {
00905 swap = T(i).vindices[0];
00906 T(i).vindices[0] = T(i).vindices[2];
00907 T(i).vindices[2] = swap;
00908
00909 if (model->numnormals) {
00910 swap = T(i).nindices[0];
00911 T(i).nindices[0] = T(i).nindices[2];
00912 T(i).nindices[2] = swap;
00913 }
00914
00915 if (model->numtexcoords) {
00916 swap = T(i).tindices[0];
00917 T(i).tindices[0] = T(i).tindices[2];
00918 T(i).tindices[2] = swap;
00919 }
00920 }
00921
00922
00923 for (i = 1; i <= model->numfacetnorms; i++) {
00924 model->facetnorms[3 * i + 0] = -model->facetnorms[3 * i + 0];
00925 model->facetnorms[3 * i + 1] = -model->facetnorms[3 * i + 1];
00926 model->facetnorms[3 * i + 2] = -model->facetnorms[3 * i + 2];
00927 }
00928
00929
00930 for (i = 1; i <= model->numnormals; i++) {
00931 model->normals[3 * i + 0] = -model->normals[3 * i + 0];
00932 model->normals[3 * i + 1] = -model->normals[3 * i + 1];
00933 model->normals[3 * i + 2] = -model->normals[3 * i + 2];
00934 }
00935 }
00936
00937
00938
00939
00940
00941
00942
00943 GLvoid
00944 glmFacetNormals(GLMmodel* model)
00945 {
00946 GLuint i;
00947 GLfloat u[3];
00948 GLfloat v[3];
00949
00950 assert(model);
00951 assert(model->vertices);
00952
00953
00954 if (model->facetnorms)
00955 free(model->facetnorms);
00956
00957
00958 model->numfacetnorms = model->numtriangles;
00959 model->facetnorms = (GLfloat*)malloc(sizeof(GLfloat) *
00960 3 * (model->numfacetnorms + 1));
00961
00962 for (i = 0; i < model->numtriangles; i++) {
00963 model->triangles[i].findex = i+1;
00964
00965 u[0] = model->vertices[3 * T(i).vindices[1] + 0] -
00966 model->vertices[3 * T(i).vindices[0] + 0];
00967 u[1] = model->vertices[3 * T(i).vindices[1] + 1] -
00968 model->vertices[3 * T(i).vindices[0] + 1];
00969 u[2] = model->vertices[3 * T(i).vindices[1] + 2] -
00970 model->vertices[3 * T(i).vindices[0] + 2];
00971
00972 v[0] = model->vertices[3 * T(i).vindices[2] + 0] -
00973 model->vertices[3 * T(i).vindices[0] + 0];
00974 v[1] = model->vertices[3 * T(i).vindices[2] + 1] -
00975 model->vertices[3 * T(i).vindices[0] + 1];
00976 v[2] = model->vertices[3 * T(i).vindices[2] + 2] -
00977 model->vertices[3 * T(i).vindices[0] + 2];
00978
00979 glmCross(u, v, &model->facetnorms[3 * (i+1)]);
00980 glmNormalize(&model->facetnorms[3 * (i+1)]);
00981 }
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 GLvoid
01001 glmVertexNormals(GLMmodel* model, GLfloat angle)
01002 {
01003 GLMnode* node;
01004 GLMnode* tail;
01005 GLMnode** members;
01006 GLfloat* normals;
01007 GLuint numnormals;
01008 GLfloat average[3];
01009 GLfloat dot, cos_angle;
01010 GLuint i, avg;
01011
01012 assert(model);
01013 assert(model->facetnorms);
01014
01015
01016 cos_angle = cos(angle * M_PI / 180.0);
01017
01018
01019 if (model->normals)
01020 free(model->normals);
01021
01022
01023 model->numnormals = model->numtriangles * 3;
01024 model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1));
01025
01026
01027
01028 members = (GLMnode**)malloc(sizeof(GLMnode*) * (model->numvertices + 1));
01029 for (i = 1; i <= model->numvertices; i++)
01030 members[i] = NULL;
01031
01032
01033 for (i = 0; i < model->numtriangles; i++) {
01034 node = (GLMnode*)malloc(sizeof(GLMnode));
01035 node->index = i;
01036 node->next = members[T(i).vindices[0]];
01037 members[T(i).vindices[0]] = node;
01038
01039 node = (GLMnode*)malloc(sizeof(GLMnode));
01040 node->index = i;
01041 node->next = members[T(i).vindices[1]];
01042 members[T(i).vindices[1]] = node;
01043
01044 node = (GLMnode*)malloc(sizeof(GLMnode));
01045 node->index = i;
01046 node->next = members[T(i).vindices[2]];
01047 members[T(i).vindices[2]] = node;
01048 }
01049
01050
01051 numnormals = 1;
01052 for (i = 1; i <= model->numvertices; i++) {
01053
01054
01055 node = members[i];
01056 if (!node)
01057 fprintf(stderr, "glmVertexNormals(): vertex w/o a triangle\n");
01058 average[0] = 0.0; average[1] = 0.0; average[2] = 0.0;
01059 avg = 0;
01060 while (node) {
01061
01062
01063
01064
01065 dot = glmDot(&model->facetnorms[3 * T(node->index).findex],
01066 &model->facetnorms[3 * T(members[i]->index).findex]);
01067 if (dot > cos_angle) {
01068 node->averaged = GL_TRUE;
01069 average[0] += model->facetnorms[3 * T(node->index).findex + 0];
01070 average[1] += model->facetnorms[3 * T(node->index).findex + 1];
01071 average[2] += model->facetnorms[3 * T(node->index).findex + 2];
01072 avg = 1;
01073 } else {
01074 node->averaged = GL_FALSE;
01075 }
01076 node = node->next;
01077 }
01078
01079 if (avg) {
01080
01081 glmNormalize(average);
01082
01083
01084 model->normals[3 * numnormals + 0] = average[0];
01085 model->normals[3 * numnormals + 1] = average[1];
01086 model->normals[3 * numnormals + 2] = average[2];
01087 avg = numnormals;
01088 numnormals++;
01089 }
01090
01091
01092 node = members[i];
01093 while (node) {
01094 if (node->averaged) {
01095
01096 if (T(node->index).vindices[0] == i)
01097 T(node->index).nindices[0] = avg;
01098 else if (T(node->index).vindices[1] == i)
01099 T(node->index).nindices[1] = avg;
01100 else if (T(node->index).vindices[2] == i)
01101 T(node->index).nindices[2] = avg;
01102 } else {
01103
01104 model->normals[3 * numnormals + 0] =
01105 model->facetnorms[3 * T(node->index).findex + 0];
01106 model->normals[3 * numnormals + 1] =
01107 model->facetnorms[3 * T(node->index).findex + 1];
01108 model->normals[3 * numnormals + 2] =
01109 model->facetnorms[3 * T(node->index).findex + 2];
01110 if (T(node->index).vindices[0] == i)
01111 T(node->index).nindices[0] = numnormals;
01112 else if (T(node->index).vindices[1] == i)
01113 T(node->index).nindices[1] = numnormals;
01114 else if (T(node->index).vindices[2] == i)
01115 T(node->index).nindices[2] = numnormals;
01116 numnormals++;
01117 }
01118 node = node->next;
01119 }
01120 }
01121
01122 model->numnormals = numnormals - 1;
01123
01124
01125 for (i = 1; i <= model->numvertices; i++) {
01126 node = members[i];
01127 while (node) {
01128 tail = node;
01129 node = node->next;
01130 free(tail);
01131 }
01132 }
01133 free(members);
01134
01135
01136
01137
01138
01139 normals = model->normals;
01140 model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1));
01141 for (i = 1; i <= model->numnormals; i++) {
01142 model->normals[3 * i + 0] = normals[3 * i + 0];
01143 model->normals[3 * i + 1] = normals[3 * i + 1];
01144 model->normals[3 * i + 2] = normals[3 * i + 2];
01145 }
01146 free(normals);
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
01156 GLvoid
01157 glmLinearTexture(GLMmodel* model)
01158 {
01159 GLMgroup *group;
01160 GLfloat dimensions[3];
01161 GLfloat x, y, scalefactor;
01162 GLuint i;
01163
01164 assert(model);
01165
01166 if (model->texcoords)
01167 free(model->texcoords);
01168 model->numtexcoords = model->numvertices;
01169 model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1));
01170
01171 glmDimensions(model, dimensions);
01172 scalefactor = 2.0 /
01173 glmAbs(glmMax(glmMax(dimensions[0], dimensions[1]), dimensions[2]));
01174
01175
01176 for(i = 1; i <= model->numvertices; i++) {
01177 x = model->vertices[3 * i + 0] * scalefactor;
01178 y = model->vertices[3 * i + 2] * scalefactor;
01179 model->texcoords[2 * i + 0] = (x + 1.0) / 2.0;
01180 model->texcoords[2 * i + 1] = (y + 1.0) / 2.0;
01181 }
01182
01183
01184 group = model->groups;
01185 while(group) {
01186 for(i = 0; i < group->numtriangles; i++) {
01187 T(group->triangles[i]).tindices[0] = T(group->triangles[i]).vindices[0];
01188 T(group->triangles[i]).tindices[1] = T(group->triangles[i]).vindices[1];
01189 T(group->triangles[i]).tindices[2] = T(group->triangles[i]).vindices[2];
01190 }
01191 group = group->next;
01192 }
01193
01194 #if 0
01195 printf("glmLinearTexture(): generated %d linear texture coordinates\n",
01196 model->numtexcoords);
01197 #endif
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 GLvoid
01212 glmSpheremapTexture(GLMmodel* model)
01213 {
01214 GLMgroup* group;
01215 GLfloat theta, phi, rho, x, y, z, r;
01216 GLuint i;
01217
01218 assert(model);
01219 assert(model->normals);
01220
01221 if (model->texcoords)
01222 free(model->texcoords);
01223 model->numtexcoords = model->numnormals;
01224 model->texcoords=(GLfloat*)malloc(sizeof(GLfloat)*2*(model->numtexcoords+1));
01225
01226 for (i = 1; i <= model->numnormals; i++) {
01227 z = model->normals[3 * i + 0];
01228 y = model->normals[3 * i + 1];
01229 x = model->normals[3 * i + 2];
01230 r = sqrt((x * x) + (y * y));
01231 rho = sqrt((r * r) + (z * z));
01232
01233 if(r == 0.0) {
01234 theta = 0.0;
01235 phi = 0.0;
01236 } else {
01237 if(z == 0.0)
01238 phi = 3.14159265 / 2.0;
01239 else
01240 phi = acos(z / rho);
01241
01242 if(y == 0.0)
01243 theta = 3.141592365 / 2.0;
01244 else
01245 theta = asin(y / r) + (3.14159265 / 2.0);
01246 }
01247
01248 model->texcoords[2 * i + 0] = theta / 3.14159265;
01249 model->texcoords[2 * i + 1] = phi / 3.14159265;
01250 }
01251
01252
01253 group = model->groups;
01254 while(group) {
01255 for (i = 0; i < group->numtriangles; i++) {
01256 T(group->triangles[i]).tindices[0] = T(group->triangles[i]).nindices[0];
01257 T(group->triangles[i]).tindices[1] = T(group->triangles[i]).nindices[1];
01258 T(group->triangles[i]).tindices[2] = T(group->triangles[i]).nindices[2];
01259 }
01260 group = group->next;
01261 }
01262 }
01263
01264
01265
01266
01267
01268 GLvoid
01269 glmDelete(GLMmodel* model)
01270 {
01271 GLMgroup* group;
01272 GLuint i;
01273
01274 assert(model);
01275
01276 if (model->pathname) free(model->pathname);
01277 if (model->mtllibname) free(model->mtllibname);
01278 if (model->vertices) free(model->vertices);
01279 if (model->normals) free(model->normals);
01280 if (model->texcoords) free(model->texcoords);
01281 if (model->facetnorms) free(model->facetnorms);
01282 if (model->triangles) free(model->triangles);
01283 if (model->materials) {
01284 for (i = 0; i < model->nummaterials; i++)
01285 free(model->materials[i].name);
01286 }
01287 free(model->materials);
01288 while(model->groups) {
01289 group = model->groups;
01290 model->groups = model->groups->next;
01291 free(group->name);
01292 free(group->triangles);
01293 free(group);
01294 }
01295
01296 free(model);
01297 }
01298
01299
01300
01301
01302
01303
01304
01305 GLMmodel*
01306 glmReadOBJ(const char* filename)
01307 {
01308 GLMmodel* model;
01309 FILE* file;
01310
01311
01312 file = fopen(filename, "r");
01313 if (!file) {
01314 fprintf(stderr, "glmReadOBJ() failed: can't open data file \"%s\".\n",
01315 filename);
01316 exit(1);
01317 }
01318
01319
01320 model = (GLMmodel*)malloc(sizeof(GLMmodel));
01321 model->pathname = strdup(filename);
01322 model->mtllibname = NULL;
01323 model->numvertices = 0;
01324 model->vertices = NULL;
01325 model->numnormals = 0;
01326 model->normals = NULL;
01327 model->numtexcoords = 0;
01328 model->texcoords = NULL;
01329 model->numfacetnorms = 0;
01330 model->facetnorms = NULL;
01331 model->numtriangles = 0;
01332 model->triangles = NULL;
01333 model->nummaterials = 0;
01334 model->materials = NULL;
01335 model->numgroups = 0;
01336 model->groups = NULL;
01337 model->position[0] = 0.0;
01338 model->position[1] = 0.0;
01339 model->position[2] = 0.0;
01340
01341
01342
01343 glmFirstPass(model, file);
01344
01345
01346 model->vertices = (GLfloat*)malloc(sizeof(GLfloat) *
01347 3 * (model->numvertices + 1));
01348 model->triangles = (GLMtriangle*)malloc(sizeof(GLMtriangle) *
01349 model->numtriangles);
01350 if (model->numnormals) {
01351 model->normals = (GLfloat*)malloc(sizeof(GLfloat) *
01352 3 * (model->numnormals + 1));
01353 }
01354 if (model->numtexcoords) {
01355 model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) *
01356 2 * (model->numtexcoords + 1));
01357 }
01358
01359
01360 rewind(file);
01361
01362 glmSecondPass(model, file);
01363
01364
01365 fclose(file);
01366
01367 return model;
01368 }
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 GLvoid
01386 glmWriteOBJ(GLMmodel* model, char* filename, GLuint mode)
01387 {
01388 GLuint i;
01389 FILE* file;
01390 GLMgroup* group;
01391
01392 assert(model);
01393
01394
01395 if (mode & GLM_FLAT && !model->facetnorms) {
01396 printf("glmWriteOBJ() warning: flat normal output requested "
01397 "with no facet normals defined.\n");
01398 mode &= ~GLM_FLAT;
01399 }
01400 if (mode & GLM_SMOOTH && !model->normals) {
01401 printf("glmWriteOBJ() warning: smooth normal output requested "
01402 "with no normals defined.\n");
01403 mode &= ~GLM_SMOOTH;
01404 }
01405 if (mode & GLM_TEXTURE && !model->texcoords) {
01406 printf("glmWriteOBJ() warning: texture coordinate output requested "
01407 "with no texture coordinates defined.\n");
01408 mode &= ~GLM_TEXTURE;
01409 }
01410 if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
01411 printf("glmWriteOBJ() warning: flat normal output requested "
01412 "and smooth normal output requested (using smooth).\n");
01413 mode &= ~GLM_FLAT;
01414 }
01415 if (mode & GLM_COLOR && !model->materials) {
01416 printf("glmWriteOBJ() warning: color output requested "
01417 "with no colors (materials) defined.\n");
01418 mode &= ~GLM_COLOR;
01419 }
01420 if (mode & GLM_MATERIAL && !model->materials) {
01421 printf("glmWriteOBJ() warning: material output requested "
01422 "with no materials defined.\n");
01423 mode &= ~GLM_MATERIAL;
01424 }
01425 if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
01426 printf("glmWriteOBJ() warning: color and material output requested "
01427 "outputting only materials.\n");
01428 mode &= ~GLM_COLOR;
01429 }
01430
01431
01432
01433 file = fopen(filename, "w");
01434 if (!file) {
01435 fprintf(stderr, "glmWriteOBJ() failed: can't open file \"%s\" to write.\n",
01436 filename);
01437 exit(1);
01438 }
01439
01440
01441 fprintf(file, "# \n");
01442 fprintf(file, "# Wavefront OBJ generated by GLM library\n");
01443 fprintf(file, "# \n");
01444 fprintf(file, "# GLM library\n");
01445 fprintf(file, "# Nate Robins\n");
01446 fprintf(file, "# ndr@pobox.com\n");
01447 fprintf(file, "# http://www.pobox.com/~ndr\n");
01448 fprintf(file, "# \n");
01449
01450 if (mode & GLM_MATERIAL && model->mtllibname) {
01451 fprintf(file, "\nmtllib %s\n\n", model->mtllibname);
01452 glmWriteMTL(model, filename, model->mtllibname);
01453 }
01454
01455
01456 fprintf(file, "\n");
01457 fprintf(file, "# %d vertices\n", model->numvertices);
01458 for (i = 1; i <= model->numvertices; i++) {
01459 fprintf(file, "v %f %f %f\n",
01460 model->vertices[3 * i + 0],
01461 model->vertices[3 * i + 1],
01462 model->vertices[3 * i + 2]);
01463 }
01464
01465
01466 if (mode & GLM_SMOOTH) {
01467 fprintf(file, "\n");
01468 fprintf(file, "# %d normals\n", model->numnormals);
01469 for (i = 1; i <= model->numnormals; i++) {
01470 fprintf(file, "vn %f %f %f\n",
01471 model->normals[3 * i + 0],
01472 model->normals[3 * i + 1],
01473 model->normals[3 * i + 2]);
01474 }
01475 } else if (mode & GLM_FLAT) {
01476 fprintf(file, "\n");
01477 fprintf(file, "# %d normals\n", model->numfacetnorms);
01478 for (i = 1; i <= model->numnormals; i++) {
01479 fprintf(file, "vn %f %f %f\n",
01480 model->facetnorms[3 * i + 0],
01481 model->facetnorms[3 * i + 1],
01482 model->facetnorms[3 * i + 2]);
01483 }
01484 }
01485
01486
01487 if (mode & GLM_TEXTURE) {
01488 fprintf(file, "\n");
01489 fprintf(file, "# %d texcoords\n", model->texcoords);
01490 for (i = 1; i <= model->numtexcoords; i++) {
01491 fprintf(file, "vt %f %f\n",
01492 model->texcoords[2 * i + 0],
01493 model->texcoords[2 * i + 1]);
01494 }
01495 }
01496
01497 fprintf(file, "\n");
01498 fprintf(file, "# %d groups\n", model->numgroups);
01499 fprintf(file, "# %d faces (triangles)\n", model->numtriangles);
01500 fprintf(file, "\n");
01501
01502 group = model->groups;
01503 while(group) {
01504 fprintf(file, "g %s\n", group->name);
01505 if (mode & GLM_MATERIAL)
01506 fprintf(file, "usemtl %s\n", model->materials[group->material].name);
01507 for (i = 0; i < group->numtriangles; i++) {
01508 if (mode & GLM_SMOOTH && mode & GLM_TEXTURE) {
01509 fprintf(file, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
01510 T(group->triangles[i]).vindices[0],
01511 T(group->triangles[i]).nindices[0],
01512 T(group->triangles[i]).tindices[0],
01513 T(group->triangles[i]).vindices[1],
01514 T(group->triangles[i]).nindices[1],
01515 T(group->triangles[i]).tindices[1],
01516 T(group->triangles[i]).vindices[2],
01517 T(group->triangles[i]).nindices[2],
01518 T(group->triangles[i]).tindices[2]);
01519 } else if (mode & GLM_FLAT && mode & GLM_TEXTURE) {
01520 fprintf(file, "f %d/%d %d/%d %d/%d\n",
01521 T(group->triangles[i]).vindices[0],
01522 T(group->triangles[i]).findex,
01523 T(group->triangles[i]).vindices[1],
01524 T(group->triangles[i]).findex,
01525 T(group->triangles[i]).vindices[2],
01526 T(group->triangles[i]).findex);
01527 } else if (mode & GLM_TEXTURE) {
01528 fprintf(file, "f %d/%d %d/%d %d/%d\n",
01529 T(group->triangles[i]).vindices[0],
01530 T(group->triangles[i]).tindices[0],
01531 T(group->triangles[i]).vindices[1],
01532 T(group->triangles[i]).tindices[1],
01533 T(group->triangles[i]).vindices[2],
01534 T(group->triangles[i]).tindices[2]);
01535 } else if (mode & GLM_SMOOTH) {
01536 fprintf(file, "f %d//%d %d//%d %d//%d\n",
01537 T(group->triangles[i]).vindices[0],
01538 T(group->triangles[i]).nindices[0],
01539 T(group->triangles[i]).vindices[1],
01540 T(group->triangles[i]).nindices[1],
01541 T(group->triangles[i]).vindices[2],
01542 T(group->triangles[i]).nindices[2]);
01543 } else if (mode & GLM_FLAT) {
01544 fprintf(file, "f %d//%d %d//%d %d//%d\n",
01545 T(group->triangles[i]).vindices[0],
01546 T(group->triangles[i]).findex,
01547 T(group->triangles[i]).vindices[1],
01548 T(group->triangles[i]).findex,
01549 T(group->triangles[i]).vindices[2],
01550 T(group->triangles[i]).findex);
01551 } else {
01552 fprintf(file, "f %d %d %d\n",
01553 T(group->triangles[i]).vindices[0],
01554 T(group->triangles[i]).vindices[1],
01555 T(group->triangles[i]).vindices[2]);
01556 }
01557 }
01558 fprintf(file, "\n");
01559 group = group->next;
01560 }
01561
01562 fclose(file);
01563 }
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579 GLvoid
01580 glmDraw(GLMmodel* model, GLuint mode)
01581 {
01582 static GLuint i;
01583 static GLMgroup* group;
01584 static GLMtriangle* triangle;
01585 static GLMmaterial* material;
01586
01587 assert(model);
01588 assert(model->vertices);
01589
01590
01591 if (mode & GLM_FLAT && !model->facetnorms) {
01592 printf("glmDraw() warning: flat render mode requested "
01593 "with no facet normals defined.\n");
01594 mode &= ~GLM_FLAT;
01595 }
01596 if (mode & GLM_SMOOTH && !model->normals) {
01597 printf("glmDraw() warning: smooth render mode requested "
01598 "with no normals defined.\n");
01599 mode &= ~GLM_SMOOTH;
01600 }
01601 if (mode & GLM_TEXTURE && !model->texcoords) {
01602 printf("glmDraw() warning: texture render mode requested "
01603 "with no texture coordinates defined.\n");
01604 mode &= ~GLM_TEXTURE;
01605 }
01606 if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
01607 printf("glmDraw() warning: flat render mode requested "
01608 "and smooth render mode requested (using smooth).\n");
01609 mode &= ~GLM_FLAT;
01610 }
01611 if (mode & GLM_COLOR && !model->materials) {
01612 printf("glmDraw() warning: color render mode requested "
01613 "with no materials defined.\n");
01614 mode &= ~GLM_COLOR;
01615 }
01616 if (mode & GLM_MATERIAL && !model->materials) {
01617 printf("glmDraw() warning: material render mode requested "
01618 "with no materials defined.\n");
01619 mode &= ~GLM_MATERIAL;
01620 }
01621 if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
01622 printf("glmDraw() warning: color and material render mode requested "
01623 "using only material mode.\n");
01624 mode &= ~GLM_COLOR;
01625 }
01626 if (mode & GLM_COLOR)
01627 glEnable(GL_COLOR_MATERIAL);
01628 else if (mode & GLM_MATERIAL)
01629 glDisable(GL_COLOR_MATERIAL);
01630
01631
01632
01633
01634
01635
01636 group = model->groups;
01637 while (group) {
01638 if (mode & GLM_MATERIAL) {
01639 material = &model->materials[group->material];
01640 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient);
01641 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse);
01642 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material->specular);
01643 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material->shininess);
01644 }
01645
01646 if (mode & GLM_COLOR) {
01647 glColor3fv(material->diffuse);
01648 }
01649
01650 glBegin(GL_TRIANGLES);
01651 for (i = 0; i < group->numtriangles; i++) {
01652 triangle = &T(group->triangles[i]);
01653
01654 if (mode & GLM_FLAT)
01655 glNormal3fv(&model->facetnorms[3 * triangle->findex]);
01656
01657 if (mode & GLM_SMOOTH)
01658 glNormal3fv(&model->normals[3 * triangle->nindices[0]]);
01659 if (mode & GLM_TEXTURE)
01660 glTexCoord2fv(&model->texcoords[2 * triangle->tindices[0]]);
01661 glVertex3fv(&model->vertices[3 * triangle->vindices[0]]);
01662
01663 if (mode & GLM_SMOOTH)
01664 glNormal3fv(&model->normals[3 * triangle->nindices[1]]);
01665 if (mode & GLM_TEXTURE)
01666 glTexCoord2fv(&model->texcoords[2 * triangle->tindices[1]]);
01667 glVertex3fv(&model->vertices[3 * triangle->vindices[1]]);
01668
01669 if (mode & GLM_SMOOTH)
01670 glNormal3fv(&model->normals[3 * triangle->nindices[2]]);
01671 if (mode & GLM_TEXTURE)
01672 glTexCoord2fv(&model->texcoords[2 * triangle->tindices[2]]);
01673 glVertex3fv(&model->vertices[3 * triangle->vindices[2]]);
01674
01675 }
01676 glEnd();
01677
01678 group = group->next;
01679 }
01680 }
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695 GLuint
01696 glmList(GLMmodel* model, GLuint mode)
01697 {
01698 GLuint list;
01699
01700 list = glGenLists(1);
01701 glNewList(list, GL_COMPILE);
01702 glmDraw(model, mode);
01703 glEndList();
01704
01705 return list;
01706 }
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716 GLvoid
01717 glmWeld(GLMmodel* model, GLfloat epsilon)
01718 {
01719 GLfloat* vectors;
01720 GLfloat* copies;
01721 GLuint numvectors;
01722 GLuint i;
01723
01724
01725 numvectors = model->numvertices;
01726 vectors = model->vertices;
01727 copies = glmWeldVectors(vectors, &numvectors, epsilon);
01728
01729 #if 0
01730 printf("glmWeld(): %d redundant vertices.\n",
01731 model->numvertices - numvectors - 1);
01732 #endif
01733
01734 for (i = 0; i < model->numtriangles; i++) {
01735 T(i).vindices[0] = (GLuint)vectors[3 * T(i).vindices[0] + 0];
01736 T(i).vindices[1] = (GLuint)vectors[3 * T(i).vindices[1] + 0];
01737 T(i).vindices[2] = (GLuint)vectors[3 * T(i).vindices[2] + 0];
01738 }
01739
01740
01741 free(vectors);
01742
01743
01744 model->numvertices = numvectors;
01745 model->vertices = (GLfloat*)malloc(sizeof(GLfloat) *
01746 3 * (model->numvertices + 1));
01747
01748
01749 for (i = 1; i <= model->numvertices; i++) {
01750 model->vertices[3 * i + 0] = copies[3 * i + 0];
01751 model->vertices[3 * i + 1] = copies[3 * i + 1];
01752 model->vertices[3 * i + 2] = copies[3 * i + 2];
01753 }
01754
01755 free(copies);
01756 }
01757
01758
01759 #if 0
01760
01761 if (model->numnormals) {
01762 numvectors = model->numnormals;
01763 vectors = model->normals;
01764 copies = glmOptimizeVectors(vectors, &numvectors);
01765
01766 printf("glmOptimize(): %d redundant normals.\n",
01767 model->numnormals - numvectors);
01768
01769 for (i = 0; i < model->numtriangles; i++) {
01770 T(i).nindices[0] = (GLuint)vectors[3 * T(i).nindices[0] + 0];
01771 T(i).nindices[1] = (GLuint)vectors[3 * T(i).nindices[1] + 0];
01772 T(i).nindices[2] = (GLuint)vectors[3 * T(i).nindices[2] + 0];
01773 }
01774
01775
01776 free(vectors);
01777
01778
01779 model->numnormals = numvectors;
01780 model->normals = (GLfloat*)malloc(sizeof(GLfloat) *
01781 3 * (model->numnormals + 1));
01782
01783
01784 for (i = 1; i <= model->numnormals; i++) {
01785 model->normals[3 * i + 0] = copies[3 * i + 0];
01786 model->normals[3 * i + 1] = copies[3 * i + 1];
01787 model->normals[3 * i + 2] = copies[3 * i + 2];
01788 }
01789
01790 free(copies);
01791 }
01792
01793
01794 if (model->numtexcoords) {
01795 numvectors = model->numtexcoords;
01796 vectors = model->texcoords;
01797 copies = glmOptimizeVectors(vectors, &numvectors);
01798
01799 printf("glmOptimize(): %d redundant texcoords.\n",
01800 model->numtexcoords - numvectors);
01801
01802 for (i = 0; i < model->numtriangles; i++) {
01803 for (j = 0; j < 3; j++) {
01804 T(i).tindices[j] = (GLuint)vectors[3 * T(i).tindices[j] + 0];
01805 }
01806 }
01807
01808
01809 free(vectors);
01810
01811
01812 model->numtexcoords = numvectors;
01813 model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) *
01814 2 * (model->numtexcoords + 1));
01815
01816
01817 for (i = 1; i <= model->numtexcoords; i++) {
01818 model->texcoords[2 * i + 0] = copies[2 * i + 0];
01819 model->texcoords[2 * i + 1] = copies[2 * i + 1];
01820 }
01821
01822 free(copies);
01823 }
01824 #endif
01825
01826 #if 0
01827
01828
01829
01830 for (i = 1; i <= model->numvertices; i++) {
01831 for (j = 0; j < model->numtriangles; i++) {
01832 if (T(j).vindices[0] == i ||
01833 T(j).vindices[1] == i ||
01834 T(j).vindices[1] == i)
01835 break;
01836 }
01837 }
01838 #endif