Blender V2.61 - r43446

mesh_validate.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2011 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * ***** END GPL LICENSE BLOCK *****
00022  */
00023 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <limits.h>
00033 
00034 #include "DNA_mesh_types.h"
00035 #include "DNA_meshdata_types.h"
00036 
00037 #include "BLO_sys_types.h"
00038 
00039 #include "BLI_utildefines.h"
00040 #include "BLI_edgehash.h"
00041 #include "BLI_math_base.h"
00042 
00043 #include "BKE_DerivedMesh.h"
00044 
00045 #include "MEM_guardedalloc.h"
00046 
00047 #include "BKE_mesh.h"
00048 #include "BKE_deform.h"
00049 
00050 #define SELECT 1
00051 
00052 typedef union {
00053     uint32_t verts[2];
00054     int64_t edval;
00055 } EdgeUUID;
00056 
00057 typedef struct SortFace {
00058 //  unsigned int    v[4];
00059     EdgeUUID        es[4];
00060     unsigned int    index;
00061 } SortFace;
00062 
00063 static void edge_store_assign(uint32_t verts[2],  const uint32_t v1, const uint32_t v2)
00064 {
00065     if(v1 < v2) {
00066         verts[0]= v1;
00067         verts[1]= v2;
00068     }
00069     else {
00070         verts[0]= v2;
00071         verts[1]= v1;
00072     }
00073 }
00074 
00075 static void edge_store_from_mface_quad(EdgeUUID es[4], MFace *mf)
00076 {
00077     edge_store_assign(es[0].verts, mf->v1, mf->v2);
00078     edge_store_assign(es[1].verts, mf->v2, mf->v3);
00079     edge_store_assign(es[2].verts, mf->v3, mf->v4);
00080     edge_store_assign(es[3].verts, mf->v4, mf->v1);
00081 }
00082 
00083 static void edge_store_from_mface_tri(EdgeUUID es[4], MFace *mf)
00084 {
00085     edge_store_assign(es[0].verts, mf->v1, mf->v2);
00086     edge_store_assign(es[1].verts, mf->v2, mf->v3);
00087     edge_store_assign(es[2].verts, mf->v3, mf->v1);
00088     es[3].verts[0] = es[3].verts[1] = UINT_MAX;
00089 }
00090 
00091 static int int64_cmp(const void *v1, const void *v2)
00092 {
00093     const int64_t x1= *(const int64_t *)v1;
00094     const int64_t x2= *(const int64_t *)v2;
00095 
00096     if( x1 > x2 ) return 1;
00097     else if( x1 < x2 ) return -1;
00098     return 0;
00099 }
00100 
00101 static int search_face_cmp(const void *v1, const void *v2)
00102 {
00103     const SortFace *sfa= v1, *sfb= v2;
00104 
00105     if  (sfa->es[0].edval > sfb->es[0].edval) return 1;
00106     else if (sfa->es[0].edval < sfb->es[0].edval) return -1;
00107 
00108     else if (sfa->es[1].edval > sfb->es[1].edval) return 1;
00109     else if (sfa->es[1].edval < sfb->es[1].edval) return -1;
00110 
00111     else if (sfa->es[2].edval > sfb->es[2].edval) return 1;
00112     else if (sfa->es[2].edval < sfb->es[2].edval) return -1;
00113 
00114     else if (sfa->es[3].edval > sfb->es[3].edval) return 1;
00115     else if (sfa->es[3].edval < sfb->es[3].edval) return -1;
00116     else                                          return 0;
00117 
00118 }
00119 
00120 #define PRINT if(do_verbose) printf
00121 
00122 int BKE_mesh_validate_arrays( Mesh *me,
00123                               MVert *mverts, unsigned int totvert,
00124                               MEdge *medges, unsigned int totedge,
00125                               MFace *mfaces, unsigned int totface,
00126                               MDeformVert *dverts, /* assume totvert length */
00127                               const short do_verbose, const short do_fixes)
00128 {
00129 #   define REMOVE_EDGE_TAG(_med) { _med->v2= _med->v1; do_edge_free= 1; }
00130 #   define REMOVE_FACE_TAG(_mf) { _mf->v3=0; do_face_free= 1; }
00131 
00132 //  MVert *mv;
00133     MEdge *med;
00134     MFace *mf;
00135     MFace *mf_prev;
00136     MVert *mvert= mverts;
00137     unsigned int i;
00138 
00139     short do_face_free= FALSE;
00140     short do_edge_free= FALSE;
00141 
00142     short verts_fixed= FALSE;
00143     short vert_weights_fixed= FALSE;
00144 
00145     int do_edge_recalc= FALSE;
00146 
00147     EdgeHash *edge_hash = BLI_edgehash_new();
00148 
00149     SortFace *sort_faces= MEM_callocN(sizeof(SortFace) * totface, "search faces");
00150     SortFace *sf;
00151     SortFace *sf_prev;
00152     unsigned int totsortface= 0;
00153 
00154     BLI_assert(!(do_fixes && me == NULL));
00155 
00156     PRINT("%s: verts(%u), edges(%u), faces(%u)\n", __func__, totvert, totedge, totface);
00157 
00158     if(totedge == 0 && totface != 0) {
00159         PRINT("    locical error, %u faces and 0 edges\n", totface);
00160         do_edge_recalc= TRUE;
00161     }
00162 
00163     for(i=1; i<totvert; i++, mvert++) {
00164         int j;
00165         int fix_normal= TRUE;
00166 
00167         for(j=0; j<3; j++) {
00168             if(!finite(mvert->co[j])) {
00169                 PRINT("    vertex %u: has invalid coordinate\n", i);
00170 
00171                 if (do_fixes) {
00172                     zero_v3(mvert->co);
00173 
00174                     verts_fixed= TRUE;
00175                 }
00176             }
00177 
00178             if(mvert->no[j]!=0)
00179                 fix_normal= FALSE;
00180         }
00181 
00182         if(fix_normal) {
00183             PRINT("    vertex %u: has zero normal, assuming Z-up normal\n", i);
00184             if (do_fixes) {
00185                 mvert->no[2]= SHRT_MAX;
00186                 verts_fixed= TRUE;
00187             }
00188         }
00189     }
00190 
00191     for(i=0, med= medges; i<totedge; i++, med++) {
00192         int remove= FALSE;
00193         if(med->v1 == med->v2) {
00194             PRINT("    edge %u: has matching verts, both %u\n", i, med->v1);
00195             remove= do_fixes;
00196         }
00197         if(med->v1 >= totvert) {
00198             PRINT("    edge %u: v1 index out of range, %u\n", i, med->v1);
00199             remove= do_fixes;
00200         }
00201         if(med->v2 >= totvert) {
00202             PRINT("    edge %u: v2 index out of range, %u\n", i, med->v2);
00203             remove= do_fixes;
00204         }
00205 
00206         if(BLI_edgehash_haskey(edge_hash, med->v1, med->v2)) {
00207             PRINT("    edge %u: is a duplicate of, %d\n", i, GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, med->v1, med->v2)));
00208             remove= do_fixes;
00209         }
00210 
00211         if(remove == FALSE){
00212             BLI_edgehash_insert(edge_hash, med->v1, med->v2, SET_INT_IN_POINTER(i));
00213         }
00214         else {
00215             REMOVE_EDGE_TAG(med);
00216         }
00217     }
00218 
00219     for(i=0, mf=mfaces, sf=sort_faces; i<totface; i++, mf++) {
00220         int remove= FALSE;
00221         int fidx;
00222         unsigned int fv[4];
00223 
00224         fidx = mf->v4 ? 3:2;
00225         do {
00226             fv[fidx]= *(&(mf->v1) + fidx);
00227             if(fv[fidx] >= totvert) {
00228                 PRINT("    face %u: 'v%d' index out of range, %u\n", i, fidx + 1, fv[fidx]);
00229                 remove= do_fixes;
00230             }
00231         } while (fidx--);
00232 
00233         if(remove == FALSE) {
00234             if(mf->v4) {
00235                 if(mf->v1 == mf->v2) { PRINT("    face %u: verts invalid, v1/v2 both %u\n", i, mf->v1); remove= do_fixes; }
00236                 if(mf->v1 == mf->v3) { PRINT("    face %u: verts invalid, v1/v3 both %u\n", i, mf->v1); remove= do_fixes;  }
00237                 if(mf->v1 == mf->v4) { PRINT("    face %u: verts invalid, v1/v4 both %u\n", i, mf->v1); remove= do_fixes;  }
00238 
00239                 if(mf->v2 == mf->v3) { PRINT("    face %u: verts invalid, v2/v3 both %u\n", i, mf->v2); remove= do_fixes;  }
00240                 if(mf->v2 == mf->v4) { PRINT("    face %u: verts invalid, v2/v4 both %u\n", i, mf->v2); remove= do_fixes;  }
00241 
00242                 if(mf->v3 == mf->v4) { PRINT("    face %u: verts invalid, v3/v4 both %u\n", i, mf->v3); remove= do_fixes;  }
00243             }
00244             else {
00245                 if(mf->v1 == mf->v2) { PRINT("    faceT %u: verts invalid, v1/v2 both %u\n", i, mf->v1); remove= do_fixes; }
00246                 if(mf->v1 == mf->v3) { PRINT("    faceT %u: verts invalid, v1/v3 both %u\n", i, mf->v1); remove= do_fixes; }
00247 
00248                 if(mf->v2 == mf->v3) { PRINT("    faceT %u: verts invalid, v2/v3 both %u\n", i, mf->v2); remove= do_fixes; }
00249             }
00250 
00251             if(remove == FALSE) {
00252                 if(totedge) {
00253                     if(mf->v4) {
00254                         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; }
00255                         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; }
00256                         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; }
00257                         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; }
00258                     }
00259                     else {
00260                         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; }
00261                         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; }
00262                         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; }
00263                     }
00264                 }
00265 
00266                 sf->index = i;
00267 
00268                 if(mf->v4) {
00269                     edge_store_from_mface_quad(sf->es, mf);
00270 
00271                     qsort(sf->es, 4, sizeof(int64_t), int64_cmp);
00272                 }
00273                 else {
00274                     edge_store_from_mface_tri(sf->es, mf);
00275                     qsort(sf->es, 3, sizeof(int64_t), int64_cmp);
00276                 }
00277 
00278                 totsortface++;
00279                 sf++;
00280             }
00281         }
00282         if(remove) {
00283             REMOVE_FACE_TAG(mf);
00284         }
00285     }
00286 
00287     qsort(sort_faces, totsortface, sizeof(SortFace), search_face_cmp);
00288 
00289     sf= sort_faces;
00290     sf_prev= sf;
00291     sf++;
00292 
00293     for(i=1; i<totsortface; i++, sf++) {
00294         int remove= FALSE;
00295         /* on a valid mesh, code below will never run */
00296         if(memcmp(sf->es, sf_prev->es, sizeof(sf_prev->es)) == 0) {
00297             mf= mfaces + sf->index;
00298 
00299             if(do_verbose) {
00300                 mf_prev= mfaces + sf_prev->index;
00301                 if(mf->v4) {
00302                     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);
00303                 }
00304                 else {
00305                     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);
00306                 }
00307             }
00308 
00309             remove= do_fixes;
00310         }
00311         else {
00312             sf_prev= sf;
00313         }
00314 
00315         if(remove) {
00316             REMOVE_FACE_TAG(mf);
00317         }
00318     }
00319 
00320     BLI_edgehash_free(edge_hash, NULL);
00321     MEM_freeN(sort_faces);
00322 
00323 
00324     /* fix deform verts */
00325     if (dverts) {
00326         MDeformVert *dv;
00327         for(i=0, dv= dverts; i<totvert; i++, dv++) {
00328             MDeformWeight *dw;
00329             unsigned int j;
00330 
00331             for(j=0, dw= dv->dw; j < dv->totweight; j++, dw++) {
00332                 /* note, greater then max defgroups is accounted for in our code, but not < 0 */
00333                 if (!finite(dw->weight)) {
00334                     PRINT("    vertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
00335                     if (do_fixes) {
00336                         dw->weight= 0.0f;
00337                         vert_weights_fixed= TRUE;
00338                     }
00339                 }
00340                 else if (dw->weight < 0.0f || dw->weight > 1.0f) {
00341                     PRINT("    vertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
00342                     if (do_fixes) {
00343                         CLAMP(dw->weight, 0.0f, 1.0f);
00344                         vert_weights_fixed= TRUE;
00345                     }
00346                 }
00347 
00348                 if (dw->def_nr < 0) {
00349                     PRINT("    vertex deform %u, has invalid group %d\n", i, dw->def_nr);
00350                     if (do_fixes) {
00351                         defvert_remove_group(dv, dw);
00352                         if (dv->dw) {
00353                             /* re-allocated, the new values compensate for stepping
00354                              * within the for loop and may not be valid */
00355                             j--;
00356                             dw= dv->dw + j;
00357 
00358                             vert_weights_fixed= TRUE;
00359                         }
00360                         else { /* all freed */
00361                             break;
00362                         }
00363                     }
00364                 }
00365             }
00366         }
00367     }
00368 
00369 
00370     PRINT("BKE_mesh_validate: finished\n\n");
00371 
00372 #    undef REMOVE_EDGE_TAG
00373 #    undef REMOVE_FACE_TAG
00374 
00375     if(me) {
00376         if(do_face_free) {
00377             mesh_strip_loose_faces(me);
00378         }
00379 
00380         if (do_edge_free) {
00381             mesh_strip_loose_edges(me);
00382         }
00383 
00384         if(do_fixes && do_edge_recalc) {
00385             BKE_mesh_calc_edges(me, TRUE);
00386         }
00387     }
00388 
00389     return (verts_fixed || vert_weights_fixed || do_face_free || do_edge_free || do_edge_recalc);
00390 }
00391 
00392 static int mesh_validate_customdata(CustomData *data, short do_verbose, const short do_fixes)
00393 {
00394     int i= 0, has_fixes= 0;
00395 
00396     while(i<data->totlayer) {
00397         CustomDataLayer *layer= &data->layers[i];
00398         CustomDataMask mask= CD_TYPE_AS_MASK(layer->type);
00399         int ok= 1;
00400 
00401         if((mask&CD_MASK_MESH)==0) {
00402             PRINT("CustomDataLayer type %d which isn't in CD_MASK_MESH is stored in Mehs structure\n", layer->type);
00403 
00404             if(do_fixes) {
00405                 CustomData_free_layer(data, layer->type, 0, i);
00406                 ok= 0;
00407                 has_fixes= 1;
00408             }
00409         }
00410 
00411         if(ok)
00412             i++;
00413     }
00414 
00415     return has_fixes;
00416 }
00417 
00418 #undef PRINT
00419 
00420 static int BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata, CustomData *fdata,
00421                                             short do_verbose, const short do_fixes)
00422 {
00423     int vfixed= 0, efixed= 0, ffixed= 0;
00424 
00425     vfixed= mesh_validate_customdata(vdata, do_verbose, do_fixes);
00426     efixed= mesh_validate_customdata(edata, do_verbose, do_fixes);
00427     ffixed= mesh_validate_customdata(fdata, do_verbose, do_fixes);
00428 
00429     return vfixed || efixed || ffixed;
00430 }
00431 
00432 int BKE_mesh_validate(Mesh *me, int do_verbose)
00433 {
00434     int layers_fixed= 0, arrays_fixed= 0;
00435 
00436     if(do_verbose) {
00437         printf("MESH: %s\n", me->id.name+2);
00438     }
00439 
00440     layers_fixed= BKE_mesh_validate_all_customdata(&me->vdata, &me->edata, &me->fdata, do_verbose, TRUE);
00441     arrays_fixed= BKE_mesh_validate_arrays(me,
00442                                            me->mvert, me->totvert,
00443                                            me->medge, me->totedge,
00444                                            me->mface, me->totface,
00445                                            me->dvert,
00446                                            do_verbose, TRUE);
00447 
00448     return layers_fixed || arrays_fixed;
00449 }
00450 
00451 int BKE_mesh_validate_dm(DerivedMesh *dm)
00452 {
00453     return BKE_mesh_validate_arrays(NULL,
00454                                     dm->getVertArray(dm), dm->getNumVerts(dm),
00455                                     dm->getEdgeArray(dm), dm->getNumEdges(dm),
00456                                     dm->getFaceArray(dm), dm->getNumFaces(dm),
00457                                     dm->getVertDataArray(dm, CD_MDEFORMVERT),
00458                                     TRUE, FALSE);
00459 }
00460 
00461 void BKE_mesh_calc_edges(Mesh *mesh, int update)
00462 {
00463     CustomData edata;
00464     EdgeHashIterator *ehi;
00465     MFace *mf = mesh->mface;
00466     MEdge *med, *med_orig;
00467     EdgeHash *eh = BLI_edgehash_new();
00468     int i, totedge, totface = mesh->totface;
00469 
00470     if(mesh->totedge==0)
00471         update= 0;
00472 
00473     if(update) {
00474         /* assume existing edges are valid
00475          * useful when adding more faces and generating edges from them */
00476         med= mesh->medge;
00477         for(i= 0; i<mesh->totedge; i++, med++)
00478             BLI_edgehash_insert(eh, med->v1, med->v2, med);
00479     }
00480 
00481     for (i = 0; i < totface; i++, mf++) {
00482         if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
00483             BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
00484         if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
00485             BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
00486 
00487         if (mf->v4) {
00488             if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
00489                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
00490             if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
00491                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
00492         } else {
00493             if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
00494                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
00495         }
00496     }
00497 
00498     totedge = BLI_edgehash_size(eh);
00499 
00500     /* write new edges into a temporary CustomData */
00501     memset(&edata, 0, sizeof(edata));
00502     CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
00503 
00504     ehi = BLI_edgehashIterator_new(eh);
00505     med = CustomData_get_layer(&edata, CD_MEDGE);
00506     for(i = 0; !BLI_edgehashIterator_isDone(ehi);
00507         BLI_edgehashIterator_step(ehi), ++i, ++med) {
00508 
00509         if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) {
00510             *med= *med_orig; /* copy from the original */
00511         } else {
00512             BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
00513             med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */
00514         }
00515     }
00516     BLI_edgehashIterator_free(ehi);
00517 
00518     /* free old CustomData and assign new one */
00519     CustomData_free(&mesh->edata, mesh->totedge);
00520     mesh->edata = edata;
00521     mesh->totedge = totedge;
00522 
00523     mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);
00524 
00525     BLI_edgehash_free(eh, NULL);
00526 }