⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glm.c

📁 计算机图形学~想必是很多人需要的~在此共享一下
💻 C
📖 第 1 页 / 共 5 页
字号:
/*          glm.c
      Nate Robins, 1997, 2000
      nate@pobox.com, http://www.pobox.com/~nate
 
      Wavefront OBJ model file format reader/writer/manipulator.

      Includes routines for generating smooth normals with
      preservation of edges, welding redundant vertices & texture
      coordinate generation (spheremap and planar projections) + more.
  */#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include "glm.h"#define T(x) (model->triangles[(x)])/* _GLMnode: general purpose node */typedef struct _GLMnode {    GLuint         index;    GLboolean      averaged;    struct _GLMnode* next;} GLMnode;/* glmMax: returns the maximum of two floats */static GLfloatglmMax(GLfloat a, GLfloat b) {    if (b > a)        return b;    return a;}/* glmAbs: returns the absolute value of a float */static GLfloatglmAbs(GLfloat f){    if (f < 0)        return -f;    return f;}/* glmDot: compute the dot product of two vectors * * u - array of 3 GLfloats (GLfloat u[3]) * v - array of 3 GLfloats (GLfloat v[3]) */static GLfloatglmDot(GLfloat* u, GLfloat* v){    assert(u); assert(v);        return u[0]*v[0] + u[1]*v[1] + u[2]*v[2];}/* glmCross: compute the cross product of two vectors * * u - array of 3 GLfloats (GLfloat u[3]) * v - array of 3 GLfloats (GLfloat v[3]) * n - array of 3 GLfloats (GLfloat n[3]) to return the cross product in */static GLvoidglmCross(GLfloat* u, GLfloat* v, GLfloat* n){    assert(u); assert(v); assert(n);        n[0] = u[1]*v[2] - u[2]*v[1];    n[1] = u[2]*v[0] - u[0]*v[2];    n[2] = u[0]*v[1] - u[1]*v[0];}/* glmNormalize: normalize a vector * * v - array of 3 GLfloats (GLfloat v[3]) to be normalized */static GLvoidglmNormalize(GLfloat* v){    GLfloat l;        assert(v);        l = (GLfloat)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);    v[0] /= l;    v[1] /= l;    v[2] /= l;}/* glmEqual: compares two vectors and returns GL_TRUE if they are * equal (within a certain threshold) or GL_FALSE if not. An epsilon * that works fairly well is 0.000001. * * u - array of 3 GLfloats (GLfloat u[3]) * v - array of 3 GLfloats (GLfloat v[3])  */static GLbooleanglmEqual(GLfloat* u, GLfloat* v, GLfloat epsilon){    if (glmAbs(u[0] - v[0]) < epsilon &&        glmAbs(u[1] - v[1]) < epsilon &&        glmAbs(u[2] - v[2]) < epsilon)     {        return GL_TRUE;    }    return GL_FALSE;}/* glmWeldVectors: eliminate (weld) vectors that are within an * epsilon of each other. * * vectors     - array of GLfloat[3]'s to be welded * numvectors - number of GLfloat[3]'s in vectors * epsilon     - maximum difference between vectors  * */GLfloat*glmWeldVectors(GLfloat* vectors, GLuint* numvectors, GLfloat epsilon){    GLfloat* copies;    GLuint   copied;    GLuint   i, j;        copies = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (*numvectors + 1));    memcpy(copies, vectors, (sizeof(GLfloat) * 3 * (*numvectors + 1)));        copied = 1;    for (i = 1; i <= *numvectors; i++) {        for (j = 1; j <= copied; j++) {            if (glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {                goto duplicate;            }        }                /* must not be any duplicates -- add to the copies array */        copies[3 * copied + 0] = vectors[3 * i + 0];        copies[3 * copied + 1] = vectors[3 * i + 1];        copies[3 * copied + 2] = vectors[3 * i + 2];        j = copied;             /* pass this along for below */        copied++;        duplicate:/* set the first component of this vector to point at the correct        index into the new copies array */        vectors[3 * i + 0] = (GLfloat)j;    }        *numvectors = copied-1;    return copies;}/* glmFindGroup: Find a group in the model */GLMgroup*glmFindGroup(GLMmodel* model, char* name){    GLMgroup* group;        assert(model);        group = model->groups;    while(group) {        if (!strcmp(name, group->name))            break;        group = group->next;    }        return group;}/* glmAddGroup: Add a group to the model */GLMgroup*glmAddGroup(GLMmodel* model, char* name){    GLMgroup* group;        group = glmFindGroup(model, name);    if (!group) {        group = (GLMgroup*)malloc(sizeof(GLMgroup));        group->name = strdup(name);        group->material = 0;        group->numtriangles = 0;        group->triangles = NULL;        group->next = model->groups;        model->groups = group;        model->numgroups++;    }        return group;}/* glmFindGroup: Find a material in the model */GLuintglmFindMaterial(GLMmodel* model, char* name){    GLuint i;        /* XXX doing a linear search on a string key'd list is pretty lame,    but it works and is fast enough for now. */    for (i = 0; i < model->nummaterials; i++) {        if (!strcmp(model->materials[i].name, name))            goto found;    }        /* didn't find the name, so print a warning and return the default    material (0). */    printf("glmFindMaterial():  can't find material \"%s\".\n", name);    i = 0;    found:    return i;}/* glmDirName: return the directory given a path * * path - filesystem path * * NOTE: the return value should be free'd. */static char*glmDirName(char* path){    char* dir;    char* s;        dir = strdup(path);        s = strrchr(dir, '/');    if (s)        s[1] = '\0';    else        dir[0] = '\0';        return dir;}/* glmReadMTL: read a wavefront material library file * * model - properly initialized GLMmodel structure * name  - name of the material library */static GLvoidglmReadMTL(GLMmodel* model, char* name){    FILE* file;    char* dir;    char* filename;    char    buf[128];    GLuint nummaterials, i;        dir = glmDirName(model->pathname);    filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1));    strcpy(filename, dir);    strcat(filename, name);    free(dir);        file = fopen(filename, "r");    if (!file) {        fprintf(stderr, "glmReadMTL() failed: can't open material file \"%s\".\n",            filename);        exit(1);    }    free(filename);        /* count the number of materials in the file */    nummaterials = 1;    while(fscanf(file, "%s", buf) != EOF) {        switch(buf[0]) {        case '#':               /* comment */            /* eat up rest of line */            fgets(buf, sizeof(buf), file);            break;        case 'n':               /* newmtl */            fgets(buf, sizeof(buf), file);            nummaterials++;            sscanf(buf, "%s %s", buf, buf);            break;        default:            /* eat up rest of line */            fgets(buf, sizeof(buf), file);            break;        }    }        rewind(file);        model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * nummaterials);    model->nummaterials = nummaterials;        /* set the default material */    for (i = 0; i < nummaterials; i++) {        model->materials[i].name = NULL;        model->materials[i].shininess = 65.0;        model->materials[i].diffuse[0] = 0.8;        model->materials[i].diffuse[1] = 0.8;        model->materials[i].diffuse[2] = 0.8;        model->materials[i].diffuse[3] = 1.0;        model->materials[i].ambient[0] = 0.2;        model->materials[i].ambient[1] = 0.2;        model->materials[i].ambient[2] = 0.2;        model->materials[i].ambient[3] = 1.0;        model->materials[i].specular[0] = 0.0;        model->materials[i].specular[1] = 0.0;        model->materials[i].specular[2] = 0.0;        model->materials[i].specular[3] = 1.0;    }    model->materials[0].name = strdup("default");        /* now, read in the data */    nummaterials = 0;    while(fscanf(file, "%s", buf) != EOF) {        switch(buf[0]) {        case '#':               /* comment */            /* eat up rest of line */            fgets(buf, sizeof(buf), file);            break;        case 'n':               /* newmtl */            fgets(buf, sizeof(buf), file);            sscanf(buf, "%s %s", buf, buf);            nummaterials++;            model->materials[nummaterials].name = strdup(buf);            break;        case 'N':            fscanf(file, "%f", &model->materials[nummaterials].shininess);            /* wavefront shininess is from [0, 1000], so scale for OpenGL */            model->materials[nummaterials].shininess /= 1000.0;            model->materials[nummaterials].shininess *= 128.0;            break;        case 'K':            switch(buf[1]) {            case 'd':                fscanf(file, "%f %f %f",                    &model->materials[nummaterials].diffuse[0],                    &model->materials[nummaterials].diffuse[1],                    &model->materials[nummaterials].diffuse[2]);                break;            case 's':                fscanf(file, "%f %f %f",                    &model->materials[nummaterials].specular[0],                    &model->materials[nummaterials].specular[1],                    &model->materials[nummaterials].specular[2]);                break;            case 'a':                fscanf(file, "%f %f %f",                    &model->materials[nummaterials].ambient[0],                    &model->materials[nummaterials].ambient[1],                    &model->materials[nummaterials].ambient[2]);                break;            default:                /* eat up rest of line */                fgets(buf, sizeof(buf), file);                break;            }            break;            default:                /* eat up rest of line */                fgets(buf, sizeof(buf), file);                break;        }    }}/* glmWriteMTL: write a wavefront material library file * * model   - properly initialized GLMmodel structure * modelpath  - pathname of the model being written * mtllibname - name of the material library to be written */static GLvoidglmWriteMTL(GLMmodel* model, char* modelpath, char* mtllibname){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -