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