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

📄 glm.c

📁 嵌入式GUI OpenGL源代码。OpenGL是嵌入式开发中常用的一种GUI系统。
💻 C
📖 第 1 页 / 共 4 页
字号:
/*          glm.c      Nate Robins, 1997      ndr@pobox.com, http://www.pobox.com/~ndr/       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){  FILE* file;  char* dir;  char* filename;  GLMmaterial* material;  GLuint i;  dir = glmDirName(modelpath);  filename = (char*)malloc(sizeof(char) * (strlen(dir)+strlen(mtllibname)));  strcpy(filename, dir);  strcat(filename, mtllibname);  free(dir);  /* open the file */  file = fopen(filename, "w");  if (!file) {    fprintf(stderr, "glmWriteMTL() failed: can't open file \"%s\".\n",	    filename);    exit(1);  }  free(filename);  /* spit out a header */  fprintf(file, "#  \n");  fprintf(file, "#  Wavefront MTL generated by GLM library\n");  fprintf(file, "#  \n");  fprintf(file, "#  GLM library\n");  fprintf(file, "#  Nate Robins\n");  fprintf(file, "#  ndr@pobox.com\n");  fprintf(file, "#  http://www.pobox.com/~ndr\n");  fprintf(file, "#  \n\n");  for (i = 0; i < model->nummaterials; i++) {    material = &model->materials[i];    fprintf(file, "newmtl %s\n", material->name);    fprintf(file, "Ka %f %f %f\n", 	    material->ambient[0], material->ambient[1], material->ambient[2]);    fprintf(file, "Kd %f %f %f\n", 	    material->diffuse[0], material->diffuse[1], material->diffuse[2]);    fprintf(file, "Ks %f %f %f\n", 	    material->specular[0],material->specular[1],material->specular[2]);    fprintf(file, "Ns %f\n", material->shininess / 128.0 * 1000.0);    fprintf(file, "\n");  }}/* glmFirstPass: first pass at a Wavefront OBJ file that gets all the * statistics of the model (such as #vertices, #normals, etc) * * model - properly initialized GLMmodel structure * file  - (fopen'd) file descriptor  */static GLvoidglmFirstPass(GLMmodel* model, FILE* file) {  GLuint    numvertices;		/* number of vertices in model */  GLuint    numnormals;			/* number of normals in model */  GLuint    numtexcoords;		/* number of texcoords in model */  GLuint    numtriangles;		/* number of triangles in model */  GLMgroup* group;			/* current group */  unsigned  v, n, t;  char      buf[128];  /* make a default group */  group = glmAddGroup(model, "default");  numvertices = numnormals = numtexcoords = numtriangles = 0;  while(fscanf(file, "%s", buf) != EOF) {    switch(buf[0]) {    case '#':				/* comment */      /* eat up rest of line */      fgets(buf, sizeof(buf), file);      break;    case 'v':				/* v, vn, vt */      switch(buf[1]) {      case '\0':			/* vertex */

⌨️ 快捷键说明

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