📄 glm.cpp
字号:
fgets(buf, sizeof(buf), file);
break;
}
}
/* set the stats in the model structure */
model->numvertices = numvertices;
model->numnormals = numnormals;
model->numtexcoords = numtexcoords;
model->numtriangles = numtriangles;
/* allocate memory for the triangles in each group */
group = model->groups;
while(group) {
group->triangles = (GLuint*)malloc(sizeof(GLuint) * group->numtriangles);
group->numtriangles = 0;
group = group->next;
}
}
/* glmSecondPass: second pass at a Wavefront OBJ file that gets all
* the data.
*
* model - properly initialized GLMmodel structure
* file - (fopen'd) file descriptor
*/
static GLvoid glmSecondPass(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 */
GLfloat* vertices; /* array of vertices */
GLfloat* normals; /* array of normals */
GLfloat* texcoords; /* array of texture coordinates */
GLMgroup* group; /* current group pointer */
GLuint material; /* current material */
GLuint v, n, t;
char buf[128];
/* set the pointer shortcuts */
vertices = model->vertices;
normals = model->normals;
texcoords = model->texcoords;
group = model->groups;
/* on the second pass through the file, read all the data into the
allocated arrays */
numvertices = numnormals = numtexcoords = 1;
numtriangles = 0;
material = 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 */
fscanf(file, "%f %f %f",
&vertices[3 * numvertices + 0],
&vertices[3 * numvertices + 1],
&vertices[3 * numvertices + 2]);
numvertices++;
break;
case 'n': /* normal */
fscanf(file, "%f %f %f",
&normals[3 * numnormals + 0],
&normals[3 * numnormals + 1],
&normals[3 * numnormals + 2]);
numnormals++;
break;
case 't': /* texcoord */
fscanf(file, "%f %f",
&texcoords[2 * numtexcoords + 0],
&texcoords[2 * numtexcoords + 1]);
numtexcoords++;
break;
}
break;
case 'u':
fgets(buf, sizeof(buf), file);
sscanf(buf, "%s %s", buf, buf);
group->material = material = glmFindMaterial(model, buf);
break;
case 'g': /* group */
/* eat up rest of line */
fgets(buf, sizeof(buf), file);
#if SINGLE_STRING_GROUP_NAMES
sscanf(buf, "%s", buf);
#else
buf[strlen(buf)-1] = '\0'; /* nuke '\n' */
#endif
group = glmFindGroup(model, buf);
group->material = material;
break;
case 'f': /* face */
v = n = t = 0;
fscanf(file, "%s", buf);
/* can be one of %d, %d//%d, %d/%d, %d/%d/%d %d//%d */
if (strstr(buf, "//")) {
/* v//n */
sscanf(buf, "%d//%d", &v, &n);
T(numtriangles).vindices[0] = v;
T(numtriangles).nindices[0] = n;
fscanf(file, "%d//%d", &v, &n);
T(numtriangles).vindices[1] = v;
T(numtriangles).nindices[1] = n;
fscanf(file, "%d//%d", &v, &n);
T(numtriangles).vindices[2] = v;
T(numtriangles).nindices[2] = n;
group->triangles[group->numtriangles++] = numtriangles;
numtriangles++;
while(fscanf(file, "%d//%d", &v, &n) > 0) {
T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
T(numtriangles).vindices[2] = v;
T(numtriangles).nindices[2] = n;
group->triangles[group->numtriangles++] = numtriangles;
numtriangles++;
}
} else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) {
/* v/t/n */
T(numtriangles).vindices[0] = v;
T(numtriangles).tindices[0] = t;
T(numtriangles).nindices[0] = n;
fscanf(file, "%d/%d/%d", &v, &t, &n);
T(numtriangles).vindices[1] = v;
T(numtriangles).tindices[1] = t;
T(numtriangles).nindices[1] = n;
fscanf(file, "%d/%d/%d", &v, &t, &n);
T(numtriangles).vindices[2] = v;
T(numtriangles).tindices[2] = t;
T(numtriangles).nindices[2] = n;
group->triangles[group->numtriangles++] = numtriangles;
numtriangles++;
while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) {
T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
T(numtriangles).nindices[0] = T(numtriangles-1).nindices[0];
T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
T(numtriangles).nindices[1] = T(numtriangles-1).nindices[2];
T(numtriangles).vindices[2] = v;
T(numtriangles).tindices[2] = t;
T(numtriangles).nindices[2] = n;
group->triangles[group->numtriangles++] = numtriangles;
numtriangles++;
}
} else if (sscanf(buf, "%d/%d", &v, &t) == 2) {
/* v/t */
T(numtriangles).vindices[0] = v;
T(numtriangles).tindices[0] = t;
fscanf(file, "%d/%d", &v, &t);
T(numtriangles).vindices[1] = v;
T(numtriangles).tindices[1] = t;
fscanf(file, "%d/%d", &v, &t);
T(numtriangles).vindices[2] = v;
T(numtriangles).tindices[2] = t;
group->triangles[group->numtriangles++] = numtriangles;
numtriangles++;
while(fscanf(file, "%d/%d", &v, &t) > 0) {
T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
T(numtriangles).tindices[0] = T(numtriangles-1).tindices[0];
T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
T(numtriangles).tindices[1] = T(numtriangles-1).tindices[2];
T(numtriangles).vindices[2] = v;
T(numtriangles).tindices[2] = t;
group->triangles[group->numtriangles++] = numtriangles;
numtriangles++;
}
} else {
/* v */
sscanf(buf, "%d", &v);
T(numtriangles).vindices[0] = v;
fscanf(file, "%d", &v);
T(numtriangles).vindices[1] = v;
fscanf(file, "%d", &v);
T(numtriangles).vindices[2] = v;
group->triangles[group->numtriangles++] = numtriangles;
numtriangles++;
while(fscanf(file, "%d", &v) > 0) {
T(numtriangles).vindices[0] = T(numtriangles-1).vindices[0];
T(numtriangles).vindices[1] = T(numtriangles-1).vindices[2];
T(numtriangles).vindices[2] = v;
group->triangles[group->numtriangles++] = numtriangles;
numtriangles++;
}
}
break;
default:
/* eat up rest of line */
fgets(buf, sizeof(buf), file);
break;
}
}
#if 0
/* announce the memory requirements */
printf(" Memory: %d bytes\n",
numvertices * 3*sizeof(GLfloat) +
numnormals * 3*sizeof(GLfloat) * (numnormals ? 1 : 0) +
numtexcoords * 3*sizeof(GLfloat) * (numtexcoords ? 1 : 0) +
numtriangles * sizeof(GLMtriangle));
#endif
}
/* glmUnitize: "unitize" a model by translating it to the origin and
* scaling it to fit in a unit cube around the origin (-1 to 1 in all
* dimensions).
* Returns the scalefactor used.
*
* model - properly initialized GLMmodel structure
*/
GLfloat glmUnitize(GLMmodel* model)
{
GLuint i;
GLfloat maxx, minx, maxy, miny, maxz, minz;
GLfloat cx, cy, cz, w, h, d;
GLfloat scale;
assert(model);
assert(model->vertices);
/* get the max/mins */
maxx = minx = model->vertices[3 + 0];
maxy = miny = model->vertices[3 + 1];
maxz = minz = model->vertices[3 + 2];
for (i = 1; i <= model->numvertices; i++) {
if (maxx < model->vertices[3 * i + 0])
maxx = model->vertices[3 * i + 0];
if (minx > model->vertices[3 * i + 0])
minx = model->vertices[3 * i + 0];
if (maxy < model->vertices[3 * i + 1])
maxy = model->vertices[3 * i + 1];
if (miny > model->vertices[3 * i + 1])
miny = model->vertices[3 * i + 1];
if (maxz < model->vertices[3 * i + 2])
maxz = model->vertices[3 * i + 2];
if (minz > model->vertices[3 * i + 2])
minz = model->vertices[3 * i + 2];
}
/* calculate model width, height, and depth */
w = glmAbs(maxx) + glmAbs(minx);
h = glmAbs(maxy) + glmAbs(miny);
d = glmAbs(maxz) + glmAbs(minz);
/* calculate center of the model */
cx = (maxx + minx) / 2.0f;
cy = (maxy + miny) / 2.0f;
cz = (maxz + minz) / 2.0f;
/* calculate unitizing scale factor */
scale = 2.0f / glmMax(glmMax(w, h), d);
/* translate around center then scale */
for (i = 1; i <= model->numvertices; i++) {
model->vertices[3 * i + 0] -= cx;
model->vertices[3 * i + 1] -= cy;
model->vertices[3 * i + 2] -= cz;
model->vertices[3 * i + 0] *= scale;
model->vertices[3 * i + 1] *= scale;
model->vertices[3 * i + 2] *= scale;
}
return scale;
}
/* glmDimensions: Calculates the dimensions (width, height, depth) of
* a model.
*
* model - initialized GLMmodel structure
* dimensions - array of 3 GLfloats (GLfloat dimensions[3])
*/
GLvoid glmDimensions(GLMmodel* model, GLfloat* dimensions)
{
GLuint i;
GLfloat maxx, minx, maxy, miny, maxz, minz;
assert(model);
assert(model->vertices);
assert(dimensions);
/* get the max/mins */
maxx = minx = model->vertices[3 + 0];
maxy = miny = model->vertices[3 + 1];
maxz = minz = model->vertices[3 + 2];
for (i = 1; i <= model->numvertices; i++) {
if (maxx < model->vertices[3 * i + 0])
maxx = model->vertices[3 * i + 0];
if (minx > model->vertices[3 * i + 0])
minx = model->vertices[3 * i + 0];
if (maxy < model->vertices[3 * i + 1])
maxy = model->vertices[3 * i + 1];
if (miny > model->vertices[3 * i + 1])
miny = model->vertices[3 * i + 1];
if (maxz < model->vertices[3 * i + 2])
maxz = model->vertices[3 * i + 2];
if (minz > model->vertices[3 * i + 2])
minz = model->vertices[3 * i + 2];
}
/* calculate model width, height, and depth */
dimensions[0] = glmAbs(maxx) + glmAbs(minx);
dimensions[1] = glmAbs(maxy) + glmAbs(miny);
dimensions[2] = glmAbs(maxz) + glmAbs(minz);
}
/* glmScale: Scales a model by a given amount.
*
* model - properly initialized GLMmodel structure
* scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
*/
GLvoid glmScale(GLMmodel* model, GLfloat scale)
{
GLuint i;
for (i = 1; i <= model->numvertices; i++) {
model->vertices[3 * i + 0] *= scale;
model->vertices[3 * i + 1] *= scale;
model->vertices[3 * i + 2] *= scale;
}
}
/* glmReverseWinding: Reverse the polygon winding for all polygons in
* this model. Default winding is counter-clockwise. Also changes
* the direction of the normals.
*
* model - properly initialized GLMmodel structure
*/
GLvoid glmReverseWinding(GLMmodel* model)
{
GLuint i, swap;
assert(model);
for (i = 0; i < model->numtriangles; i++) {
swap = T(i).vindices[0];
T(i).vindices[0] = T(i).vindices[2];
T(i).vindices[2] = swap;
if (model->numnormals) {
swap = T(i).nindices[0];
T(i).nindices[0] = T(i).nindices[2];
T(i).nindices[2] = swap;
}
if (model->numtexcoords) {
swap = T(i).tindices[0];
T(i).tindices[0] = T(i).tindices[2];
T(i).tindices[2] = swap;
}
}
/* reverse facet normals */
for (i = 1; i <= model->numfacetnorms; i++) {
model->facetnorms[3 * i + 0] = -model->facetnorms[3 * i + 0];
model->facetnorms[3 * i + 1] = -model->facetnorms[3 * i + 1];
model->facetnorms[3 * i + 2] = -model->facetnorms[3 * i + 2];
}
/* reverse vertex normals */
for (i = 1; i <= model->numnormals; i++) {
model->normals[3 * i + 0] = -model->normals[3 * i + 0];
model->normals[3 * i + 1] = -model->normals[3 * i + 1];
model->normals[3 * i + 2] = -model->normals[3 * i + 2];
}
}
/* glmFacetNormals: Generates facet normals for a model (by taking the
* cross product of the two vectors derived from the sides of each
* triangle). Assumes a counter-clockwise winding.
*
* model - initialized GLMmodel structure
*/
GLvoid glmFacetNormals(GLMmodel* model)
{
GLuint i;
GLfloat u[3];
GLfloat v[3];
assert(model);
assert(model->vertices);
/* clobber any old facetnormals */
if (model->facetnorms)
free(model->facetnorms);
/* allocate memory for the new facet normals */
model->numfacetnorms = model->numtriangles;
model->facetnorms = (GLfloat*)malloc(sizeof(GLfloat) *
3 * (model->numfacetnorms + 1));
for (i = 0; i < model->numtriangles; i++) {
model->triangles[i].findex = i+1;
u[0] = model->vertices[3 * T(i).vindices[1] + 0] -
model->vertices[3 * T(i).vindices[0] + 0];
u[1] = model->vertices[3 * T(i).vindices[1] + 1] -
model->vertices[3 * T(i).vindices[0] + 1];
u[2] = model->vertices[3 * T(i).vindices[1] + 2] -
model->vertices[3 * T(i).vindices[0] + 2];
v[0] = model->vertices[3 * T(i).vindices[2] + 0] -
model->vertices[3 * T(i).vindices[0] + 0];
v[1] = model->vertices[3 * T(i).vindices[2] + 1] -
model->vertices[3 * T(i).vindices[0] + 1];
v[2] = model->vertices[3 * T(i).vindices[2] + 2] -
model->vertices[3 * T(i).vindices[0] + 2];
glmCross(u, v, &model->facetnorms[3 * (i+1)]);
glmNormalize(&model->facetnorms[3 * (i+1)]);
}
}
/* glmVertexNormals: Generates smooth vertex normals for a model.
* First builds a list of all the triangles each vertex is in. Then
* loops through each vertex in the the list averaging all the facet
* normals of the triangles each vertex is in. Finally, sets the
* normal index in the triangle for the vertex to the generated smooth
* normal. If the dot product of a facet normal and the facet normal
* associated with the first triangle in the list of triangles the
* current vertex is in is greater than the cosine of the angle
* parameter to the function, that facet normal is not added into the
* average normal calculation and the corresponding vertex is given
* the facet normal. This tends to preserve hard edges. The angle to
* use depends on the model, but 90 degrees is usually a good start.
*
* model - initialized GLMmodel structure
* angle - maximum angle (in degrees) to smooth across
*/
GLvoid glmVertexNormals(GLMmodel* model, GLfloat angle)
{
GLMnode* node;
GLMnode* tail;
GLMnode** members;
GLfloat* normals;
GLuint numnormals;
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 = fcos(angle * M_PI / 180.0f);
/* 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));
/* 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -