/*! * Calculates the vertex normals corresponding to the smoothing group * settings for each face of a mesh. * * \param mesh A pointer to the mesh to calculate the normals for. * \param normalL A pointer to a buffer to store the calculated * normals. The buffer must have the size: * 3*sizeof(Lib3dsVector)*mesh->faces. * * To allocate the normal buffer do for example the following: * \code * Lib3dsVector *normalL = malloc(3*sizeof(Lib3dsVector)*mesh->faces); * \endcode * * To access the normal of the i-th vertex of the j-th face do the * following: * \code * normalL[3*j+i] * \endcode */voidlib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL){ Lib3dsFaces **fl; Lib3dsFaces *fa; unsigned i,j,k; if (!mesh->faces) { return; } fl=calloc(sizeof(Lib3dsFaces*),mesh->points); ASSERT(fl); fa=calloc(sizeof(Lib3dsFaces),3*mesh->faces); ASSERT(fa); k=0; for (i=0; i<mesh->faces; ++i) { Lib3dsFace *f=&mesh->faceL[i]; for (j=0; j<3; ++j) { Lib3dsFaces* l=&fa[k++]; ASSERT(f->points[j]<mesh->points); l->face=f; l->next=fl[f->points[j]]; fl[f->points[j]]=l; } } for (i=0; i<mesh->faces; ++i) { Lib3dsFace *f=&mesh->faceL[i]; for (j=0; j<3; ++j) { // FIXME: static array needs at least check!! Lib3dsVector n,N[64]; Lib3dsFaces *p; int k,l; int found; ASSERT(f->points[j]<mesh->points); if (f->smoothing) { lib3ds_vector_zero(n); k=0; for (p=fl[f->points[j]]; p; p=p->next) { found=0; for (l=0; l<k; ++l) { if (fabs(lib3ds_vector_dot(N[l], p->face->normal)-1.0)<1e-5) { found=1; break; } } if (!found) { if (f->smoothing & p->face->smoothing) { lib3ds_vector_add(n,n, p->face->normal); lib3ds_vector_copy(N[k], p->face->normal); ++k; } } } } else { lib3ds_vector_copy(n, f->normal); } lib3ds_vector_normalize(n); lib3ds_vector_copy(normalL[3*i+j], n); } } free(fa); free(fl);}