Merging r41246 through r41535 from trunk into soc-2011-tomato
[blender.git] / source / blender / blenkernel / intern / mesh_validate.c
index 7c38688c82e2bb83855605244deca9918f5833b9..0dac4b8cd808c251cba3d0c45d73e94942ee3b59 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -80,7 +78,7 @@ static void edge_store_from_mface_quad(EdgeUUID es[4], MFace *mf)
        edge_store_assign(es[3].verts, mf->v4, mf->v1);
 }
 
-static void edge_store_from_mface_tri(EdgeUUID es[3], MFace *mf)
+static void edge_store_from_mface_tri(EdgeUUID es[4], MFace *mf)
 {
        edge_store_assign(es[0].verts, mf->v1, mf->v2);
        edge_store_assign(es[1].verts, mf->v2, mf->v3);
@@ -117,9 +115,10 @@ static int search_face_cmp(const void *v1, const void *v2)
 
 }
 
+#define PRINT if(do_verbose) printf
+
 int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totvert, MEdge *medges, unsigned int totedge, MFace *mfaces, unsigned int totface, const short do_verbose, const short do_fixes)
 {
-#      define PRINT if(do_verbose) printf
 #      define REMOVE_EDGE_TAG(_med) { _med->v2= _med->v1; do_edge_free= 1; }
 #      define REMOVE_FACE_TAG(_mf) { _mf->v3=0; do_face_free= 1; }
 
@@ -143,30 +142,30 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totve
 
        BLI_assert(!(do_fixes && me == NULL));
 
-       PRINT("ED_mesh_validate: verts(%d), edges(%d), faces(%d)\n", totvert, totedge, totface);
+       PRINT("%s: verts(%u), edges(%u), faces(%u)\n", __func__, totvert, totedge, totface);
 
        if(totedge == 0 && totface != 0) {
-               PRINT("    locical error, %d faces and 0 edges\n", totface);
+               PRINT("    locical error, %u faces and 0 edges\n", totface);
                do_edge_recalc= TRUE;
        }
 
        for(i=0, med= medges; i<totedge; i++, med++) {
                int remove= FALSE;
                if(med->v1 == med->v2) {
-                       PRINT("    edge %d: has matching verts, both %d\n", i, med->v1);
+                       PRINT("    edge %u: has matching verts, both %u\n", i, med->v1);
                        remove= do_fixes;
                }
                if(med->v1 >= totvert) {
-                       PRINT("    edge %d: v1 index out of range, %d\n", i, med->v1);
+                       PRINT("    edge %u: v1 index out of range, %u\n", i, med->v1);
                        remove= do_fixes;
                }
                if(med->v2 >= totvert) {
-                       PRINT("    edge %d: v2 index out of range, %d\n", i, med->v2);
+                       PRINT("    edge %u: v2 index out of range, %u\n", i, med->v2);
                        remove= do_fixes;
                }
 
                if(BLI_edgehash_haskey(edge_hash, med->v1, med->v2)) {
-                       PRINT("    edge %d: is a duplicate of, %d\n", i, GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, med->v1, med->v2)));
+                       PRINT("    edge %u: is a duplicate of, %d\n", i, GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, med->v1, med->v2)));
                        remove= do_fixes;
                }
 
@@ -187,41 +186,41 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totve
                do {
                        fv[fidx]= *(&(mf->v1) + fidx);
                        if(fv[fidx] >= totvert) {
-                               PRINT("    face %d: 'v%d' index out of range, %d\n", i, fidx + 1, fv[fidx]);
+                               PRINT("    face %u: 'v%d' index out of range, %u\n", i, fidx + 1, fv[fidx]);
                                remove= do_fixes;
                        }
                } while (fidx--);
 
                if(remove == FALSE) {
                        if(mf->v4) {
-                               if(mf->v1 == mf->v2) { PRINT("    face %d: verts invalid, v1/v2 both %d\n", i, mf->v1); remove= do_fixes; }
-                               if(mf->v1 == mf->v3) { PRINT("    face %d: verts invalid, v1/v3 both %d\n", i, mf->v1); remove= do_fixes;  }
-                               if(mf->v1 == mf->v4) { PRINT("    face %d: verts invalid, v1/v4 both %d\n", i, mf->v1); remove= do_fixes;  }
+                               if(mf->v1 == mf->v2) { PRINT("    face %u: verts invalid, v1/v2 both %u\n", i, mf->v1); remove= do_fixes; }
+                               if(mf->v1 == mf->v3) { PRINT("    face %u: verts invalid, v1/v3 both %u\n", i, mf->v1); remove= do_fixes;  }
+                               if(mf->v1 == mf->v4) { PRINT("    face %u: verts invalid, v1/v4 both %u\n", i, mf->v1); remove= do_fixes;  }
 
-                               if(mf->v2 == mf->v3) { PRINT("    face %d: verts invalid, v2/v3 both %d\n", i, mf->v2); remove= do_fixes;  }
-                               if(mf->v2 == mf->v4) { PRINT("    face %d: verts invalid, v2/v4 both %d\n", i, mf->v2); remove= do_fixes;  }
+                               if(mf->v2 == mf->v3) { PRINT("    face %u: verts invalid, v2/v3 both %u\n", i, mf->v2); remove= do_fixes;  }
+                               if(mf->v2 == mf->v4) { PRINT("    face %u: verts invalid, v2/v4 both %u\n", i, mf->v2); remove= do_fixes;  }
 
-                               if(mf->v3 == mf->v4) { PRINT("    face %d: verts invalid, v3/v4 both %d\n", i, mf->v3); remove= do_fixes;  }
+                               if(mf->v3 == mf->v4) { PRINT("    face %u: verts invalid, v3/v4 both %u\n", i, mf->v3); remove= do_fixes;  }
                        }
                        else {
-                               if(mf->v1 == mf->v2) { PRINT("    faceT %d: verts invalid, v1/v2 both %d\n", i, mf->v1); remove= do_fixes; }
-                               if(mf->v1 == mf->v3) { PRINT("    faceT %d: verts invalid, v1/v3 both %d\n", i, mf->v1); remove= do_fixes; }
+                               if(mf->v1 == mf->v2) { PRINT("    faceT %u: verts invalid, v1/v2 both %u\n", i, mf->v1); remove= do_fixes; }
+                               if(mf->v1 == mf->v3) { PRINT("    faceT %u: verts invalid, v1/v3 both %u\n", i, mf->v1); remove= do_fixes; }
 
-                               if(mf->v2 == mf->v3) { PRINT("    faceT %d: verts invalid, v2/v3 both %d\n", i, mf->v2); remove= do_fixes; }
+                               if(mf->v2 == mf->v3) { PRINT("    faceT %u: verts invalid, v2/v3 both %u\n", i, mf->v2); remove= do_fixes; }
                        }
 
                        if(remove == FALSE) {
                                if(totedge) {
                                        if(mf->v4) {
-                                               if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) { PRINT("    face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); do_edge_recalc= TRUE; }
-                                               if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) { PRINT("    face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); do_edge_recalc= TRUE; }
-                                               if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v4)) { PRINT("    face %d: edge v3/v4 (%d,%d) is missing egde data\n", i, mf->v3, mf->v4); do_edge_recalc= TRUE; }
-                                               if(!BLI_edgehash_haskey(edge_hash, mf->v4, mf->v1)) { PRINT("    face %d: edge v4/v1 (%d,%d) is missing egde data\n", i, mf->v4, mf->v1); do_edge_recalc= TRUE; }
+                                               if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) { PRINT("    face %u: edge v1/v2 (%u,%u) is missing egde data\n", i, mf->v1, mf->v2); do_edge_recalc= TRUE; }
+                                               if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) { PRINT("    face %u: edge v2/v3 (%u,%u) is missing egde data\n", i, mf->v2, mf->v3); do_edge_recalc= TRUE; }
+                                               if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v4)) { PRINT("    face %u: edge v3/v4 (%u,%u) is missing egde data\n", i, mf->v3, mf->v4); do_edge_recalc= TRUE; }
+                                               if(!BLI_edgehash_haskey(edge_hash, mf->v4, mf->v1)) { PRINT("    face %u: edge v4/v1 (%u,%u) is missing egde data\n", i, mf->v4, mf->v1); do_edge_recalc= TRUE; }
                                        }
                                        else {
-                                               if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) { PRINT("    face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); do_edge_recalc= TRUE; }
-                                               if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) { PRINT("    face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); do_edge_recalc= TRUE; }
-                                               if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v1)) { PRINT("    face %d: edge v3/v1 (%d,%d) is missing egde data\n", i, mf->v3, mf->v1); do_edge_recalc= TRUE; }
+                                               if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) { PRINT("    face %u: edge v1/v2 (%u,%u) is missing egde data\n", i, mf->v1, mf->v2); do_edge_recalc= TRUE; }
+                                               if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) { PRINT("    face %u: edge v2/v3 (%u,%u) is missing egde data\n", i, mf->v2, mf->v3); do_edge_recalc= TRUE; }
+                                               if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v1)) { PRINT("    face %u: edge v3/v1 (%u,%u) is missing egde data\n", i, mf->v3, mf->v1); do_edge_recalc= TRUE; }
                                        }
                                }
 
@@ -261,10 +260,10 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totve
                        if(do_verbose) {
                                mf_prev= mfaces + sf_prev->index;
                                if(mf->v4) {
-                                       PRINT("    face %d & %d: are duplicates (%d,%d,%d,%d) (%d,%d,%d,%d)\n", sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4, mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4);
+                                       PRINT("    face %u & %u: are duplicates (%u,%u,%u,%u) (%u,%u,%u,%u)\n", sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4, mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4);
                                }
                                else {
-                                       PRINT("    face %d & %d: are duplicates (%d,%d,%d) (%d,%d,%d)\n", sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf_prev->v1, mf_prev->v2, mf_prev->v3);
+                                       PRINT("    face %u & %u: are duplicates (%u,%u,%u) (%u,%u,%u)\n", sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf_prev->v1, mf_prev->v2, mf_prev->v3);
                                }
                        }
 
@@ -284,7 +283,6 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totve
 
        PRINT("BKE_mesh_validate: finished\n\n");
 
-#       undef PRINT
 #       undef REMOVE_EDGE_TAG
 #       undef REMOVE_FACE_TAG
 
@@ -305,10 +303,57 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totve
        return (do_face_free || do_edge_free || do_edge_recalc);
 }
 
+static int mesh_validate_customdata(CustomData *data, short do_verbose, const short do_fixes)
+{
+       int i= 0, has_fixes= 0;
+
+       while(i<data->totlayer) {
+               CustomDataLayer *layer= &data->layers[i];
+               int mask= 1 << layer->type;
+               int ok= 1;
+
+               if((mask&CD_MASK_MESH)==0) {
+                       PRINT("CustomDataLayer type %d which isn't in CD_MASK_MESH is stored in Mehs structure\n", layer->type);
+
+                       if(do_fixes) {
+                               CustomData_free_layer(data, layer->type, 0, i);
+                               ok= 0;
+                               has_fixes= 1;
+                       }
+               }
+
+               if(ok)
+                       i++;
+       }
+
+       return has_fixes;
+}
+
+#undef PRINT
+
+int BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata, CustomData *fdata, short do_verbose, const short do_fixes)
+{
+       int vfixed= 0, efixed= 0, ffixed= 0;
+
+       vfixed= mesh_validate_customdata(vdata, do_verbose, do_fixes);
+       efixed= mesh_validate_customdata(edata, do_verbose, do_fixes);
+       ffixed= mesh_validate_customdata(fdata, do_verbose, do_fixes);
+
+       return vfixed || efixed || ffixed;
+}
+
 int BKE_mesh_validate(Mesh *me, int do_verbose)
 {
-       printf("MESH: %s\n", me->id.name+2);
-       return BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, do_verbose, TRUE);
+       int layers_fixed= 0, arrays_fixed= 0;
+
+       if(do_verbose) {
+               printf("MESH: %s\n", me->id.name+2);
+       }
+
+       layers_fixed= BKE_mesh_validate_all_customdata(&me->vdata, &me->edata, &me->fdata, do_verbose, TRUE);
+       arrays_fixed= BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, do_verbose, TRUE);
+
+       return layers_fixed || arrays_fixed;
 }
 
 int BKE_mesh_validate_dm(DerivedMesh *dm)