// Add a line to glm.h as follows: typedef struct _GLMmodel { char* pathname; /* path to this model */ char* mtllibname; /* name of the material library */ GLuint numvertices; /* number of vertices in model */ GLfloat* vertices; /* array of vertices */ GLfloat* normArray; // ADD THIS LINE. GLuint numnormals; /* number of normals in model */ GLfloat* normals; /* array of normals */ // Use "normArray" instead of "normals" for your normal array // when using in a vertex array. // Replace your glmVertexNormals in glm.cpp by this: GLvoid glmVertexNormals(GLMmodel* model, GLfloat angle) { GLMnode* node; GLMnode* tail; GLMnode** members; GLfloat* normals; GLuint numnormals, tmpCount; GLfloat average[3]; GLfloat dot, cos_angle; GLuint i, avg; assert(model); assert(model->facetnorms); /* calculate the cosine of the angle (in degrees) */ cos_angle = cos(angle * M_PI / 180.0); /* nuke any previous normals */ if (model->normals) free(model->normals); /* allocate space for new normals */ model->numnormals = model->numtriangles * 3; /* 3 normals per triangle */ model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1)); model->normArray = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1)); /* allocate a structure that will hold a linked list of triangle indices for each vertex */ members = (GLMnode**)malloc(sizeof(GLMnode*) * (model->numvertices + 1)); for (i = 1; i <= model->numvertices; i++) members[i] = NULL; /* for every triangle, create a node for each vertex in it */ for (i = 0; i < model->numtriangles; i++) { node = (GLMnode*)malloc(sizeof(GLMnode)); node->index = i; node->next = members[T(i).vindices[0]]; members[T(i).vindices[0]] = node; node = (GLMnode*)malloc(sizeof(GLMnode)); node->index = i; node->next = members[T(i).vindices[1]]; members[T(i).vindices[1]] = node; node = (GLMnode*)malloc(sizeof(GLMnode)); node->index = i; node->next = members[T(i).vindices[2]]; members[T(i).vindices[2]] = node; } /* calculate the average normal for each vertex */ tmpCount = numnormals = 1; for (i = 1; i <= model->numvertices; i++) { /* calculate an average normal for this vertex by averaging the facet normal of every triangle this vertex is in */ node = members[i]; if (!node) fprintf(stderr, "glmVertexNormals(): vertex w/o a triangle\n"); average[0] = 0.0; average[1] = 0.0; average[2] = 0.0; avg = 0; while (node) { /* only average if the dot product of the angle between the two facet normals is greater than the cosine of the threshold angle -- or, said another way, the angle between the two facet normals is less than (or equal to) the threshold angle */ dot = glmDot(&model->facetnorms[3 * T(node->index).findex], &model->facetnorms[3 * T(members[i]->index).findex]); if (dot > cos_angle) { node->averaged = GL_TRUE; average[0] += model->facetnorms[3 * T(node->index).findex + 0]; average[1] += model->facetnorms[3 * T(node->index).findex + 1]; average[2] += model->facetnorms[3 * T(node->index).findex + 2]; avg = 1; /* we averaged at least one normal! */ } else { node->averaged = GL_FALSE; } node = node->next; } if (avg) { /* normalize the averaged normal */ glmNormalize(average); /* add the normal to the vertex normals list */ model->normals[3 * numnormals + 0] = average[0]; model->normals[3 * numnormals + 1] = average[1]; model->normals[3 * numnormals + 2] = average[2]; avg = numnormals; numnormals++; } glmNormalize(average); model->normArray[3 * tmpCount + 0] = average[0]; model->normArray[3 * tmpCount + 1] = average[1]; model->normArray[3 * tmpCount + 2] = average[2]; tmpCount++; /* set the normal of this vertex in each triangle it is in */ node = members[i]; while (node) { if (node->averaged) { /* if this node was averaged, use the average normal */ if (T(node->index).vindices[0] == i) T(node->index).nindices[0] = avg; else if (T(node->index).vindices[1] == i) T(node->index).nindices[1] = avg; else if (T(node->index).vindices[2] == i) T(node->index).nindices[2] = avg; } else { /* if this node wasn't averaged, use the facet normal */ model->normals[3 * numnormals + 0] = model->facetnorms[3 * T(node->index).findex + 0]; model->normals[3 * numnormals + 1] = model->facetnorms[3 * T(node->index).findex + 1]; model->normals[3 * numnormals + 2] = model->facetnorms[3 * T(node->index).findex + 2]; if (T(node->index).vindices[0] == i) T(node->index).nindices[0] = numnormals; else if (T(node->index).vindices[1] == i) T(node->index).nindices[1] = numnormals; else if (T(node->index).vindices[2] == i) T(node->index).nindices[2] = numnormals; numnormals++; } node = node->next; } } model->numnormals = numnormals - 1; /* free the member information */ for (i = 1; i <= model->numvertices; i++) { node = members[i]; while (node) { tail = node; node = node->next; free(tail); } } free(members); /* pack the normals array (we previously allocated the maximum number of normals that could possibly be created (numtriangles * 3), so get rid of some of them (usually alot unless none of the facet normals were averaged)) */ normals = model->normals; model->normals = (GLfloat*)malloc(sizeof(GLfloat)* 3* (model->numnormals+1)); for (i = 1; i <= model->numnormals; i++) { model->normals[3 * i + 0] = normals[3 * i + 0]; model->normals[3 * i + 1] = normals[3 * i + 1]; model->normals[3 * i + 2] = normals[3 * i + 2]; } free(normals); }