📄 glm.c
字号:
* GLM_MATERIAL - render with materials * GLM_COLOR and GLM_MATERIAL should not both be specified. * GLM_FLAT and GLM_SMOOTH should not both be specified. */GLvoidglmWriteOBJ(GLMmodel* model, char* filename, GLuint mode){ GLuint i; FILE* file; GLMgroup* group; assert(model); /* do a bit of warning */ if (mode & GLM_FLAT && !model->facetnorms) { printf("glmWriteOBJ() warning: flat normal output requested " "with no facet normals defined.\n"); mode &= ~GLM_FLAT; } if (mode & GLM_SMOOTH && !model->normals) { printf("glmWriteOBJ() warning: smooth normal output requested " "with no normals defined.\n"); mode &= ~GLM_SMOOTH; } if (mode & GLM_TEXTURE && !model->texcoords) { printf("glmWriteOBJ() warning: texture coordinate output requested " "with no texture coordinates defined.\n"); mode &= ~GLM_TEXTURE; } if (mode & GLM_FLAT && mode & GLM_SMOOTH) { printf("glmWriteOBJ() warning: flat normal output requested " "and smooth normal output requested (using smooth).\n"); mode &= ~GLM_FLAT; } if (mode & GLM_COLOR && !model->materials) { printf("glmWriteOBJ() warning: color output requested " "with no colors (materials) defined.\n"); mode &= ~GLM_COLOR; } if (mode & GLM_MATERIAL && !model->materials) { printf("glmWriteOBJ() warning: material output requested " "with no materials defined.\n"); mode &= ~GLM_MATERIAL; } if (mode & GLM_COLOR && mode & GLM_MATERIAL) { printf("glmDraw() warning: color and material output requested " "outputting only materials.\n"); mode &= ~GLM_COLOR; } /* open the file */ file = fopen(filename, "w"); if (!file) { fprintf(stderr, "glmWriteOBJ() failed: can't open file \"%s\" to write.\n", filename); exit(1); } /* spit out a header */ fprintf(file, "# \n"); fprintf(file, "# Wavefront OBJ 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"); if (mode & GLM_MATERIAL && model->mtllibname) { fprintf(file, "\nmtllib %s\n\n", model->mtllibname); glmWriteMTL(model, filename, model->mtllibname); } /* spit out the vertices */ fprintf(file, "\n"); fprintf(file, "# %d vertices\n", model->numvertices); for (i = 1; i <= model->numvertices; i++) { fprintf(file, "v %f %f %f\n", model->vertices[3 * i + 0], model->vertices[3 * i + 1], model->vertices[3 * i + 2]); } /* spit out the smooth/flat normals */ if (mode & GLM_SMOOTH) { fprintf(file, "\n"); fprintf(file, "# %d normals\n", model->numnormals); for (i = 1; i <= model->numnormals; i++) { fprintf(file, "vn %f %f %f\n", model->normals[3 * i + 0], model->normals[3 * i + 1], model->normals[3 * i + 2]); } } else if (mode & GLM_FLAT) { fprintf(file, "\n"); fprintf(file, "# %d normals\n", model->numfacetnorms); for (i = 1; i <= model->numnormals; i++) { fprintf(file, "vn %f %f %f\n", model->facetnorms[3 * i + 0], model->facetnorms[3 * i + 1], model->facetnorms[3 * i + 2]); } } /* spit out the texture coordinates */ if (mode & GLM_TEXTURE) { fprintf(file, "\n"); fprintf(file, "# %d texcoords\n", model->texcoords); for (i = 1; i <= model->numtexcoords; i++) { fprintf(file, "vt %f %f\n", model->texcoords[2 * i + 0], model->texcoords[2 * i + 1]); } } fprintf(file, "\n"); fprintf(file, "# %d groups\n", model->numgroups); fprintf(file, "# %d faces (triangles)\n", model->numtriangles); fprintf(file, "\n"); group = model->groups; while(group) { fprintf(file, "g %s\n", group->name); if (mode & GLM_MATERIAL) fprintf(file, "usemtl %s\n", model->materials[group->material].name); for (i = 0; i < group->numtriangles; i++) { if (mode & GLM_SMOOTH && mode & GLM_TEXTURE) { fprintf(file, "f %d/%d/%d %d/%d/%d %d/%d/%d\n", T(group->triangles[i]).vindices[0], T(group->triangles[i]).nindices[0], T(group->triangles[i]).tindices[0], T(group->triangles[i]).vindices[1], T(group->triangles[i]).nindices[1], T(group->triangles[i]).tindices[1], T(group->triangles[i]).vindices[2], T(group->triangles[i]).nindices[2], T(group->triangles[i]).tindices[2]); } else if (mode & GLM_FLAT && mode & GLM_TEXTURE) { fprintf(file, "f %d/%d %d/%d %d/%d\n", T(group->triangles[i]).vindices[0], T(group->triangles[i]).findex, T(group->triangles[i]).vindices[1], T(group->triangles[i]).findex, T(group->triangles[i]).vindices[2], T(group->triangles[i]).findex); } else if (mode & GLM_TEXTURE) { fprintf(file, "f %d/%d %d/%d %d/%d\n", T(group->triangles[i]).vindices[0], T(group->triangles[i]).tindices[0], T(group->triangles[i]).vindices[1], T(group->triangles[i]).tindices[1], T(group->triangles[i]).vindices[2], T(group->triangles[i]).tindices[2]); } else if (mode & GLM_SMOOTH) { fprintf(file, "f %d//%d %d//%d %d//%d\n", T(group->triangles[i]).vindices[0], T(group->triangles[i]).nindices[0], T(group->triangles[i]).vindices[1], T(group->triangles[i]).nindices[1], T(group->triangles[i]).vindices[2], T(group->triangles[i]).nindices[2]); } else if (mode & GLM_FLAT) { fprintf(file, "f %d//%d %d//%d %d//%d\n", T(group->triangles[i]).vindices[0], T(group->triangles[i]).findex, T(group->triangles[i]).vindices[1], T(group->triangles[i]).findex, T(group->triangles[i]).vindices[2], T(group->triangles[i]).findex); } else { fprintf(file, "f %d %d %d\n", T(group->triangles[i]).vindices[0], T(group->triangles[i]).vindices[1], T(group->triangles[i]).vindices[2]); } } fprintf(file, "\n"); group = group->next; } fclose(file);}/* glmDraw: Renders the model to the current OpenGL context using the * mode specified. * * model - initialized GLMmodel structure * mode - a bitwise OR of values describing what is to be rendered. * GLM_NONE - render with only vertices * GLM_FLAT - render with facet normals * GLM_SMOOTH - render with vertex normals * GLM_TEXTURE - render with texture coords * GLM_COLOR - render with colors (color material) * GLM_MATERIAL - render with materials * GLM_COLOR and GLM_MATERIAL should not both be specified. * GLM_FLAT and GLM_SMOOTH should not both be specified. */GLvoidglmDraw(GLMmodel* model, GLuint mode){ static GLuint i; static GLMgroup* group; static GLMtriangle* triangle; static GLMmaterial* material; assert(model); assert(model->vertices); /* do a bit of warning */ if (mode & GLM_FLAT && !model->facetnorms) { printf("glmDraw() warning: flat render mode requested " "with no facet normals defined.\n"); mode &= ~GLM_FLAT; } if (mode & GLM_SMOOTH && !model->normals) { printf("glmDraw() warning: smooth render mode requested " "with no normals defined.\n"); mode &= ~GLM_SMOOTH; } if (mode & GLM_TEXTURE && !model->texcoords) { printf("glmDraw() warning: texture render mode requested " "with no texture coordinates defined.\n"); mode &= ~GLM_TEXTURE; } if (mode & GLM_FLAT && mode & GLM_SMOOTH) { printf("glmDraw() warning: flat render mode requested " "and smooth render mode requested (using smooth).\n"); mode &= ~GLM_FLAT; } if (mode & GLM_COLOR && !model->materials) { printf("glmDraw() warning: color render mode requested " "with no materials defined.\n"); mode &= ~GLM_COLOR; } if (mode & GLM_MATERIAL && !model->materials) { printf("glmDraw() warning: material render mode requested " "with no materials defined.\n"); mode &= ~GLM_MATERIAL; } if (mode & GLM_COLOR && mode & GLM_MATERIAL) { printf("glmDraw() warning: color and material render mode requested " "using only material mode.\n"); mode &= ~GLM_COLOR; } if (mode & GLM_COLOR) glEnable(GL_COLOR_MATERIAL); else if (mode & GLM_MATERIAL) glDisable(GL_COLOR_MATERIAL); /* perhaps this loop should be unrolled into material, color, flat, smooth, etc. loops? since most cpu's have good branch prediction schemes (and these branches will always go one way), probably wouldn't gain too much? */ group = model->groups; while (group) { if (mode & GLM_MATERIAL) { material = &model->materials[group->material]; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material->specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material->shininess); } if (mode & GLM_COLOR) { material = &model->materials[group->material]; glColor3fv(material->diffuse); } glBegin(GL_TRIANGLES); for (i = 0; i < group->numtriangles; i++) { triangle = &T(group->triangles[i]); if (mode & GLM_FLAT) glNormal3fv(&model->facetnorms[3 * triangle->findex]); if (mode & GLM_SMOOTH) glNormal3fv(&model->normals[3 * triangle->nindices[0]]); if (mode & GLM_TEXTURE) glTexCoord2fv(&model->texcoords[2 * triangle->tindices[0]]); glVertex3fv(&model->vertices[3 * triangle->vindices[0]]); if (mode & GLM_SMOOTH) glNormal3fv(&model->normals[3 * triangle->nindices[1]]); if (mode & GLM_TEXTURE) glTexCoord2fv(&model->texcoords[2 * triangle->tindices[1]]); glVertex3fv(&model->vertices[3 * triangle->vindices[1]]); if (mode & GLM_SMOOTH) glNormal3fv(&model->normals[3 * triangle->nindices[2]]); if (mode & GLM_TEXTURE) glTexCoord2fv(&model->texcoords[2 * triangle->tindices[2]]); glVertex3fv(&model->vertices[3 * triangle->vindices[2]]); } glEnd(); group = group->next; }}/* glmList: Generates and returns a display list for the model using * the mode specified. * * model - initialized GLMmodel structure * mode - a bitwise OR of values describing what is to be rendered. * GLM_NONE - render with only vertices * GLM_FLAT - render with facet normals * GLM_SMOOTH - render with vertex normals * GLM_TEXTURE - render with texture coords * GLM_COLOR - render with colors (color material) * GLM_MATERIAL - render with materials * GLM_COLOR and GLM_MATERIAL should not both be specified. * GLM_FLAT and GLM_SMOOTH should not both be specified. */GLuintglmList(GLMmodel* model, GLuint mode){ GLuint list; list = glGenLists(1); glNewList(list, GL_COMPILE); glmDraw(model, mode); glEndList(); return list;}/* glmWeld: eliminate (weld) vectors that are within an epsilon of * each other. * * model - initialized GLMmodel structure * epsilon - maximum difference between vertices * ( 0.00001 is a good start for a unitized model) * */GLuintglmWeld(GLMmodel* model, GLfloat epsilon){ GLfloat* vectors; GLfloat* copies; GLuint numvectors; GLuint i, welded; /* vertices */ numvectors = model->numvertices; vectors = model->vertices; copies = glmWeldVectors(vectors, &numvectors, epsilon); welded = model->numvertices - numvectors - 1; for (i = 0; i < model->numtriangles; i++) { T(i).vindices[0] = (GLuint)vectors[3 * T(i).vindices[0] + 0]; T(i).vindices[1] = (GLuint)vectors[3 * T(i).vindices[1] + 0]; T(i).vindices[2] = (GLuint)vectors[3 * T(i).vindices[2] + 0]; } /* free space for old vertices */ free(vectors); /* allocate space for the new vertices */ model->numvertices = numvectors; model->vertices = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (model->numvertices + 1)); /* copy the optimized vertices into the actual vertex list */ for (i = 1; i <= model->numvertices; i++) { model->vertices[3 * i + 0] = copies[3 * i + 0]; model->vertices[3 * i + 1] = copies[3 * i + 1]; model->vertices[3 * i + 2] = copies[3 * i + 2]; } free(copies); return welded;}#if 0 /* normals */ if (model->numnormals) { numvectors = model->numnormals; vectors = model->normals; copies = glmOptimizeVectors(vectors, &numvectors); printf("glmOptimize(): %d redundant normals.\n", model->numnormals - numvectors); for (i = 0; i < model->numtriangles; i++) { T(i).nindices[0] = (GLuint)vectors[3 * T(i).nindices[0] + 0]; T(i).nindices[1] = (GLuint)vectors[3 * T(i).nindices[1] + 0]; T(i).nindices[2] = (GLuint)vectors[3 * T(i).nindices[2] + 0]; } /* free space for old normals */ free(vectors); /* allocate space for the new normals */ model->numnormals = numvectors; model->normals = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (model->numnormals + 1)); /* copy the optimized vertices into the actual vertex list */ for (i = 1; i <= model->numnormals; i++) { model->normals[3 * i + 0] = copies[3 * i + 0]; model->normals[3 * i + 1] = copies[3 * i + 1]; model->normals[3 * i + 2] = copies[3 * i + 2]; } free(copies); } /* texcoords */ if (model->numtexcoords) { numvectors = model->numtexcoords; vectors = model->texcoords; copies = glmOptimizeVectors(vectors, &numvectors); printf("glmOptimize(): %d redundant texcoords.\n", model->numtexcoords - numvectors); for (i = 0; i < model->numtriangles; i++) { for (j = 0; j < 3; j++) { T(i).tindices[j] = (GLuint)vectors[3 * T(i).tindices[j] + 0]; } } /* free space for old texcoords */ free(vectors); /* allocate space for the new texcoords */ model->numtexcoords = numvectors; model->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * 2 * (model->numtexcoords + 1)); /* copy the optimized vertices into the actual vertex list */ for (i = 1; i <= model->numtexcoords; i++) { model->texcoords[2 * i + 0] = copies[2 * i + 0]; model->texcoords[2 * i + 1] = copies[2 * i + 1]; } free(copies); }#endif#if 0 /* look for unused vertices */ /* look for unused normals */ /* look for unused texcoords */ for (i = 1; i <= model->numvertices; i++) { for (j = 0; j < model->numtriangles; i++) { if (T(j).vindices[0] == i || T(j).vindices[1] == i || T(j).vindices[1] == i) break; } }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -