📄 glm.c
字号:
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) { 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) * */GLvoidglmWeld(GLMmodel* model, GLfloat epsilon){ GLfloat* vectors; GLfloat* copies; GLuint numvectors; GLuint i; /* vertices */ numvectors = model->numvertices; vectors = model->vertices; copies = glmWeldVectors(vectors, &numvectors, epsilon); #if 0 printf("glmWeld(): %d redundant vertices.\n", model->numvertices - numvectors - 1);#endif 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);}/* glmReadPPM: read a PPM raw (type P6) file. The PPM file has a header
* that should look something like:
*
* P6
* # comment
* width height max_value
* rgbrgbrgb...
*
* where "P6" is the magic cookie which identifies the file type and
* should be the only characters on the first line followed by a
* carriage return. Any line starting with a # mark will be treated
* as a comment and discarded. After the magic cookie, three integer
* values are expected: width, height of the image and the maximum
* value for a pixel (max_value must be < 256 for PPM raw files). The
* data section consists of width*height rgb triplets (one byte each)
* in binary format (i.e., such as that written with fwrite() or
* equivalent).
*
* The rgb data is returned as an array of unsigned chars (packed
* rgb). The malloc()'d memory should be free()'d by the caller. If
* an error occurs, an error message is sent to stderr and NULL is
* returned.
*
* filename - name of the .ppm file.
* width - will contain the width of the image on return.
* height - will contain the height of the image on return.
*
*/
GLubyte*
glmReadPPM(char* filename, int* width, int* height)
{
FILE* fp;
int i, w, h, d;
unsigned char* image;
char head[70]; /* max line <= 70 in PPM (per spec). */
fp = fopen(filename, "rb");
if (!fp) {
perror(filename);
return NULL;
}
/* grab first two chars of the file and make sure that it has the
correct magic cookie for a raw PPM file. */
fgets(head, 70, fp);
if (strncmp(head, "P6", 2)) {
fprintf(stderr, "%s: Not a raw PPM file\n", filename);
return NULL;
}
/* grab the three elements in the header (width, height, maxval). */
i = 0;
while(i < 3) {
fgets(head, 70, fp);
if (head[0] == '#') /* skip comments. */
continue;
if (i == 0)
i += sscanf(head, "%d %d %d", &w, &h, &d);
else if (i == 1)
i += sscanf(head, "%d %d", &h, &d);
else if (i == 2)
i += sscanf(head, "%d", &d);
}
/* grab all the image data in one fell swoop. */
image = (unsigned char*)malloc(sizeof(unsigned char)*w*h*3);
fread(image, sizeof(unsigned char), w*h*3, fp);
fclose(fp);
*width = w;
*height = h;
return image;
}
#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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -