added mesh_calc_normals_ex() which is mesh_calc_normals() with an option to skip recalculating the vertex normals (only calculate poly/face normals instead).

also removed unneeded allocation of face normals.

otherwise no functional change.
This commit is contained in:
Campbell Barton
2011-12-06 22:55:41 +00:00
parent 35e80c5544
commit cead1e1977
5 changed files with 109 additions and 54 deletions

View File

@@ -156,6 +156,7 @@ int CustomData_number_of_layers(const struct CustomData *data, int type);
void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type);
void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
int type, const char *name);
int CustomData_is_referenced_layer(struct CustomData *data, int type);
/* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
* zero for the layer type, so only layer types specified by the mask

View File

@@ -136,8 +136,13 @@ void mesh_strip_loose_edges(struct Mesh *me);
* and vertex normals are stored in actual mverts.
*/
void mesh_calc_normals(struct MVert *mverts, int numVerts, struct MLoop *mloop,
struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
struct MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3]);
/* extended version of 'mesh_calc_normals' with option not to calc vertex normals */
void mesh_calc_normals_ex(struct MVert *mverts, int numVerts, struct MLoop *mloop,
struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
struct MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3],
const short only_face_normals);
/* Return a newly MEM_malloc'd array of all the mesh vertex locations
* (_numVerts_r_ may be NULL) */

View File

@@ -1740,6 +1740,20 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
return layer->data;
}
int CustomData_is_referenced_layer(struct CustomData *data, int type)
{
CustomDataLayer *layer;
int layer_index;
/* get the layer index of the first layer of type */
layer_index = CustomData_get_active_layer_index(data, type);
if(layer_index < 0) return 0;
layer = &data->layers[layer_index];
return (layer->flag & CD_FLAG_NOFREE) != 0;
}
void CustomData_free_temporary(CustomData *data, int totelem)
{
CustomDataLayer *layer;

View File

@@ -1668,69 +1668,111 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth)
me->totpoly, NULL, NULL, 0, NULL, NULL);
}
void mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
int UNUSED(numLoops), int numPolys, float (*polyNors_r)[3], MFace *mfaces, int numFaces,
int *origIndexFace, float (*faceNors_r)[3])
void mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
int numLoops, int numPolys, float (*polyNors_r)[3], MFace *mfaces, int numFaces,
int *origIndexFace, float (*faceNors_r)[3])
{
mesh_calc_normals_ex(mverts, numVerts, mloop, mpolys,
numLoops, numPolys, polyNors_r, mfaces, numFaces,
origIndexFace, faceNors_r, TRUE);
}
void mesh_calc_normals_ex(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
int UNUSED(numLoops), int numPolys, float (*polyNors_r)[3], MFace *mfaces, int numFaces,
int *origIndexFace, float (*faceNors_r)[3],
const short only_face_normals)
{
float (*pnors)[3] = polyNors_r, (*fnors)[3] = faceNors_r;
float (*tnorms)[3], (*edgevecbuf)[3];
float **vertcos = NULL, **vertnos = NULL;
BLI_array_declare(vertcos);
BLI_array_declare(vertnos);
int i, j, maxPolyVerts = 0;
int i, j;
MFace *mf;
MPoly *mp;
MLoop *ml;
int maxPolyVerts = 0;
if (numPolys == 0) {
return;
}
mp = mpolys;
for (i=0; i<numPolys; i++, mp++) {
maxPolyVerts = MAX2(mp->totloop, maxPolyVerts);
if (only_face_normals == FALSE) {
mp = mpolys;
for (i=0; i<numPolys; i++, mp++) {
maxPolyVerts = MAX2(mp->totloop, maxPolyVerts);
}
if (maxPolyVerts == 0) {
return;
}
}
if (maxPolyVerts == 0) {
/* if we are not calculating verts and no verts were passes thene we have nothign to do */
if ((only_face_normals == TRUE) && (polyNors_r == NULL) && (faceNors_r == NULL)) {
printf("%s: called with nothing to do\n", __func__);
return;
}
/*first go through and calculate normals for all the polys*/
edgevecbuf = MEM_callocN(sizeof(float)*3*maxPolyVerts, "edgevecbuf mesh.c");
tnorms = MEM_callocN(sizeof(float)*3*numVerts, "tnorms mesh.c");
if (!pnors)
pnors = MEM_callocN(sizeof(float)*3*numPolys, "poly_nors mesh.c");
if (!fnors)
fnors = MEM_callocN(sizeof(float)*3*numFaces, "face nors mesh.c");
mp = mpolys;
for (i=0; i<numPolys; i++, mp++) {
mesh_calc_poly_normal(mp, mloop+mp->loopstart, mverts, pnors[i]);
ml = mloop + mp->loopstart;
if (!pnors) pnors = MEM_callocN(sizeof(float) * 3 * numPolys, "poly_nors mesh.c");
/* if (!fnors) fnors = MEM_callocN(sizeof(float) * 3 * numFaces, "face nors mesh.c"); */ /* NO NEED TO ALLOC YET */
BLI_array_empty(vertcos);
BLI_array_empty(vertnos);
for (j=0; j<mp->totloop; j++) {
int vindex = ml[j].v;
BLI_array_append(vertcos, mverts[vindex].co);
BLI_array_append(vertnos, tnorms[vindex]);
if (only_face_normals == FALSE) {
/* vertex normals are optional, they require some extra calculations,
* so make them optional */
float (*tnorms)[3], (*edgevecbuf)[3];
float **vertcos = NULL, **vertnos = NULL;
BLI_array_declare(vertcos);
BLI_array_declare(vertnos);
/*first go through and calculate normals for all the polys*/
edgevecbuf = MEM_callocN(sizeof(float)*3*maxPolyVerts, "edgevecbuf mesh.c");
tnorms = MEM_callocN(sizeof(float)*3*numVerts, "tnorms mesh.c");
mp = mpolys;
for (i=0; i<numPolys; i++, mp++) {
mesh_calc_poly_normal(mp, mloop+mp->loopstart, mverts, pnors[i]);
ml = mloop + mp->loopstart;
BLI_array_empty(vertcos);
BLI_array_empty(vertnos);
for (j=0; j<mp->totloop; j++) {
int vindex = ml[j].v;
BLI_array_append(vertcos, mverts[vindex].co);
BLI_array_append(vertnos, tnorms[vindex]);
}
accumulate_vertex_normals_poly(vertnos, pnors[i], vertcos, edgevecbuf, mp->totloop);
}
accumulate_vertex_normals_poly(vertnos, pnors[i], vertcos, edgevecbuf, mp->totloop);
}
/* following Mesh convention; we use vertex coordinate itself for normal in this case */
for(i=0; i<numVerts; i++) {
MVert *mv= &mverts[i];
float *no= tnorms[i];
if(normalize_v3(no) == 0.0f)
normalize_v3_v3(no, mv->co);
BLI_array_free(vertcos);
BLI_array_free(vertnos);
MEM_freeN(edgevecbuf);
normal_float_to_short_v3(mv->no, no);
/* following Mesh convention; we use vertex coordinate itself for normal in this case */
for(i=0; i<numVerts; i++) {
MVert *mv= &mverts[i];
float *no= tnorms[i];
if(normalize_v3(no) == 0.0f)
normalize_v3_v3(no, mv->co);
normal_float_to_short_v3(mv->no, no);
}
MEM_freeN(tnorms);
}
if (origIndexFace && fnors==faceNors_r && numFaces) {
else {
/* only calc poly normals */
mp = mpolys;
for (i=0; i<numPolys; i++, mp++) {
mesh_calc_poly_normal(mp, mloop+mp->loopstart, mverts, pnors[i]);
}
}
if ( origIndexFace &&
/* fnors==faceNors_r */ /* NO NEED TO ALLOC YET */
fnors != NULL &&
numFaces)
{
mf = mfaces;
for (i=0; i<numFaces; i++, mf++, origIndexFace++) {
if (*origIndexFace < numPolys) {
@@ -1742,15 +1784,9 @@ void mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
}
}
BLI_array_free(vertcos);
BLI_array_free(vertnos);
MEM_freeN(edgevecbuf);
MEM_freeN(tnorms);
if (fnors != faceNors_r)
MEM_freeN(fnors);
if (pnors != polyNors_r)
MEM_freeN(pnors);
if (pnors != polyNors_r) MEM_freeN(pnors);
/* if (fnors != faceNors_r) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */
fnors = pnors = NULL;
}

View File

@@ -2363,7 +2363,6 @@ void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3],
/* Add weighted face normal component into normals of the face vertices.
Caller must pass pre-allocated vdiffs of nverts length. */
#define VERT_BUF_SIZE 100
void accumulate_vertex_normals_poly(float **vertnos, float polyno[3],
float **vertcos, float vdiffs[][3], int nverts)
{