From 3e8ddef8e570757dab6fd9b51aa0088e03d4aaaf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Feb 2011 02:28:11 +0000 Subject: move validation into blender kernel so it can be called by internal modifier funcs more easily. --- source/blender/blenkernel/intern/mesh_validate.c | 259 +++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 source/blender/blenkernel/intern/mesh_validate.c (limited to 'source/blender/blenkernel/intern/mesh_validate.c') diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c new file mode 100644 index 00000000000..4cef8c5560e --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -0,0 +1,259 @@ +/** + * $Id: mesh_ops.c 34569 2011-01-30 16:19:08Z ton $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_utildefines.h" +#include "BLI_edgehash.h" + +#include "BKE_DerivedMesh.h" + +#include "MEM_guardedalloc.h" + +#include "ED_mesh.h" + +typedef struct SearchFace { + unsigned int v[4]; + unsigned int index; +} SearchFace; + +static int uint_cmp(const void *v1, const void *v2) +{ + const unsigned int x1= GET_INT_FROM_POINTER(v1), x2= GET_INT_FROM_POINTER(v2); + + if( x1 > x2 ) return 1; + else if( x1 < x2 ) return -1; + return 0; +} + +static int search_face_cmp(const void *v1, const void *v2) +{ + const SearchFace *sfa= v1, *sfb= v2; + + if (sfa->v[0] > sfb->v[0]) return 1; + else if (sfa->v[0] < sfb->v[0]) return -1; + + if (sfa->v[1] > sfb->v[1]) return 1; + else if (sfa->v[1] < sfb->v[1]) return -1; + + if (sfa->v[2] > sfb->v[2]) return 1; + else if (sfa->v[2] < sfb->v[2]) return -1; + + if (sfa->v[3] > sfb->v[3]) return 1; + else if (sfa->v[3] < sfb->v[3]) return -1; + + return 0; +} + +void BKE_mesh_validate_arrays(MVert *UNUSED(mverts), int totvert, MEdge *medges, int totedge, MFace *mfaces, int totface) +{ +// MVert *mv; + MEdge *med; + MFace *mf; + int i; + + EdgeHash *edge_hash = BLI_edgehash_new(); + + SearchFace *search_faces= MEM_callocN(sizeof(SearchFace) * totface, "search faces"); + SearchFace *sf; + SearchFace *sf_prev; + + printf("ED_mesh_validate: verts(%d), edges(%d), faces(%d)\n", totvert, totedge, totface); + + if(totedge==0 && totface != 0) { + printf(" locical error, %d faces and 0 edges\n", totface); + } + + for(i=0, med=medges; iv1 == med->v2) { + printf(" edge %d: has matching verts, both %d\n", i, med->v1); + } + if(med->v1 < 0 || med->v1 >= totvert) { + printf(" edge %d: v1 index out of range, %d\n", i, med->v1); + } + if(med->v2 < 0 || med->v2 >= totvert) { + printf(" edge %d: v2 index out of range, %d\n", i, med->v2); + } + + if(BLI_edgehash_haskey(edge_hash, med->v1, med->v2)) { + printf(" edge %d: is a duplicate of, %d\n", i, GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, med->v1, med->v2))); + } + + BLI_edgehash_insert(edge_hash, med->v1, med->v2, SET_INT_IN_POINTER(i)); + } + + for(i=0, mf=mfaces; iv4 ? 3:2; + do { + fverts[fidx]= *(&mf->v1 + fidx); + if(fverts[fidx] < 0 || fverts[fidx] >= totvert) { + printf(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, fverts[fidx]); + } + } while (fidx--); + + if(mf->v4) { + if(mf->v1 == mf->v2) printf(" face %d: verts invalid, v1/v2 both %d\n", i, mf->v1); + if(mf->v1 == mf->v3) printf(" face %d: verts invalid, v1/v3 both %d\n", i, mf->v1); + if(mf->v1 == mf->v4) printf(" face %d: verts invalid, v1/v4 both %d\n", i, mf->v1); + + if(mf->v2 == mf->v3) printf(" face %d: verts invalid, v2/v3 both %d\n", i, mf->v2); + if(mf->v2 == mf->v4) printf(" face %d: verts invalid, v2/v4 both %d\n", i, mf->v2); + + if(mf->v3 == mf->v4) printf(" face %d: verts invalid, v3/v4 both %d\n", i, mf->v3); + + if(totedge) { + if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) printf(" face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); + if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) printf(" face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); + if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v4)) printf(" face %d: edge v3/v4 (%d,%d) is missing egde data\n", i, mf->v3, mf->v4); + if(!BLI_edgehash_haskey(edge_hash, mf->v4, mf->v1)) printf(" face %d: edge v4/v1 (%d,%d) is missing egde data\n", i, mf->v4, mf->v1); + } + /* TODO, avoid double lookop */ + /* + fedges[0]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v1, mf->v2)); + fedges[1]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v2, mf->v3)); + fedges[2]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v3, mf->v4)); + fedges[3]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v4, mf->v1)); + */ + qsort(fverts, 4, sizeof(int), uint_cmp); + } + else { + if(mf->v1 == mf->v2) printf(" face %d: verts invalid, v1/v2 both %d\n", i, mf->v1); + if(mf->v1 == mf->v3) printf(" face %d: verts invalid, v1/v3 both %d\n", i, mf->v1); + + if(mf->v2 == mf->v3) printf(" face %d: verts invalid, v2/v3 both %d\n", i, mf->v2); + + if(totedge) { + if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) printf(" face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); + if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) printf(" face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); + if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v1)) printf(" face %d: edge v3/v1 (%d,%d) is missing egde data\n", i, mf->v3, mf->v1); + } + /* TODO, avoid double lookop */ + /* + fedges[0]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v1, mf->v2)); + fedges[1]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v2, mf->v3)); + fedges[2]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v3, mf->v1)); + */ + qsort(fverts, 3, sizeof(int), uint_cmp); + } + + search_faces[i].index = i; + + if(mf->v4) { + search_faces[i].v[0] = fverts[0]; + search_faces[i].v[1] = fverts[1]; + search_faces[i].v[2] = fverts[2]; + search_faces[i].v[3] = fverts[3]; + } + else { + search_faces[i].v[0] = fverts[0]; + search_faces[i].v[1] = fverts[1]; + search_faces[i].v[2] = fverts[2]; + search_faces[i].v[3] = UINT_MAX; + } + } + + qsort(search_faces, totface, sizeof(SearchFace), search_face_cmp); + + sf= search_faces; + sf_prev= sf; + sf++; + + for(i=1; iv, sf_prev->v, sizeof(sf_prev->v)) == 0) { + /* slow, could be smarter here */ + MFace *mf= mfaces + sf->index; + MFace *mf_prev= mfaces + sf_prev->index; + int size_expect, size_found; + + EdgeHash *eh_tmp= BLI_edgehash_new(); + if(mf->v4) { + BLI_edgehash_insert(eh_tmp, mf->v1, mf->v2, NULL); + BLI_edgehash_insert(eh_tmp, mf->v2, mf->v3, NULL); + BLI_edgehash_insert(eh_tmp, mf->v3, mf->v4, NULL); + BLI_edgehash_insert(eh_tmp, mf->v4, mf->v1, NULL); + + BLI_edgehash_insert(eh_tmp, mf_prev->v1, mf_prev->v2, NULL); + BLI_edgehash_insert(eh_tmp, mf_prev->v2, mf_prev->v3, NULL); + BLI_edgehash_insert(eh_tmp, mf_prev->v3, mf_prev->v4, NULL); + BLI_edgehash_insert(eh_tmp, mf_prev->v4, mf_prev->v1, NULL); + + size_expect= 4; + } + else { + BLI_edgehash_insert(eh_tmp, mf->v1, mf->v2, NULL); + BLI_edgehash_insert(eh_tmp, mf->v2, mf->v3, NULL); + BLI_edgehash_insert(eh_tmp, mf->v3, mf->v1, NULL); + + BLI_edgehash_insert(eh_tmp, mf_prev->v1, mf_prev->v2, NULL); + BLI_edgehash_insert(eh_tmp, mf_prev->v2, mf_prev->v3, NULL); + BLI_edgehash_insert(eh_tmp, mf_prev->v3, mf_prev->v1, NULL); + + size_expect= 3; + } + + size_found= BLI_edgehash_size(eh_tmp); + BLI_edgehash_free(eh_tmp, NULL); + + if(size_found != size_expect) { + printf(" face %d & %d: are duplicates ", sf->index, sf_prev->index); + if(mf->v4) { + printf("(%d,%d,%d,%d) ", mf->v1, mf->v2, mf->v3, mf->v4); + printf("(%d,%d,%d,%d)\n", mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4); + } + else { + printf("(%d,%d,%d) ", mf->v1, mf->v2, mf->v3); + printf("(%d,%d,%d)\n", mf_prev->v1, mf_prev->v2, mf_prev->v3); + } + } + } + } + + BLI_edgehash_free(edge_hash, NULL); + MEM_freeN(search_faces); + + printf("BKE_mesh_validate: finished\n\n"); +} + +void BKE_mesh_validate(Mesh *me) +{ + printf("MESH: %s\n", me->id.name+2); + BKE_mesh_validate_arrays(me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface); +} + +void BKE_mesh_validate_dm(DerivedMesh *dm) +{ + BKE_mesh_validate_arrays(dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm)); +} -- cgit v1.2.3 From 5e1eb9b4d3006f81456698964d8bd5da0a28eb0c Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Wed, 9 Feb 2011 03:48:40 +0000 Subject: SVN maintenance. --- source/blender/blenkernel/intern/mesh_validate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/mesh_validate.c') diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 4cef8c5560e..9cec9da15ba 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -1,5 +1,5 @@ /** - * $Id: mesh_ops.c 34569 2011-01-30 16:19:08Z ton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * -- cgit v1.2.3 From 5aa72b87262c1dd310c5dba7cd772b3d6b02a427 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Feb 2011 15:13:20 +0000 Subject: BKE_mesh_validate() now corrects invalid meshes (optionally), added access for python so it can correct for bad imported geometry - mesh.validate(). --- source/blender/blenkernel/intern/mesh_validate.c | 355 ++++++++++++++++------- 1 file changed, 250 insertions(+), 105 deletions(-) (limited to 'source/blender/blenkernel/intern/mesh_validate.c') diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 9cec9da15ba..84b7307b820 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -31,6 +31,8 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "BLO_sys_types.h" + #include "BLI_utildefines.h" #include "BLI_edgehash.h" @@ -38,13 +40,47 @@ #include "MEM_guardedalloc.h" -#include "ED_mesh.h" +#include "BKE_mesh.h" + +#define SELECT 1 typedef struct SearchFace { unsigned int v[4]; unsigned int index; } SearchFace; +typedef union { + uint32_t verts[2]; + int64_t edval; +} EdgeStore; + +static void edge_store_assign(uint32_t verts[2], const uint32_t v1, const uint32_t v2) +{ + if(v1 < v2) { + verts[0]= v1; + verts[1]= v2; + } + else { + verts[0]= v2; + verts[1]= v1; + } +} + +static void edge_store_from_mface_quad(EdgeStore es[3], MFace *mf) +{ + edge_store_assign(es[0].verts, mf->v1, mf->v2); + edge_store_assign(es[1].verts, mf->v2, mf->v3); + edge_store_assign(es[2].verts, mf->v3, mf->v4); + edge_store_assign(es[2].verts, mf->v4, mf->v1); +} + +static void edge_store_from_mface_tri(EdgeStore es[3], MFace *mf) +{ + edge_store_assign(es[0].verts, mf->v1, mf->v2); + edge_store_assign(es[1].verts, mf->v2, mf->v3); + edge_store_assign(es[2].verts, mf->v3, mf->v1); +} + static int uint_cmp(const void *v1, const void *v2) { const unsigned int x1= GET_INT_FROM_POINTER(v1), x2= GET_INT_FROM_POINTER(v2); @@ -73,187 +109,296 @@ static int search_face_cmp(const void *v1, const void *v2) return 0; } -void BKE_mesh_validate_arrays(MVert *UNUSED(mverts), int totvert, MEdge *medges, int totedge, MFace *mfaces, int totface) +void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge *medges, int totedge, MFace *mfaces, 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; } + // MVert *mv; MEdge *med; MFace *mf; int i; + int do_face_free= FALSE; + int do_edge_free= FALSE; + + int do_edge_recalc= FALSE; + EdgeHash *edge_hash = BLI_edgehash_new(); SearchFace *search_faces= MEM_callocN(sizeof(SearchFace) * totface, "search faces"); SearchFace *sf; SearchFace *sf_prev; + int totsearchface= 0; - printf("ED_mesh_validate: verts(%d), edges(%d), faces(%d)\n", totvert, totedge, totface); + BLI_assert(!(do_fixes && me == NULL)); - if(totedge==0 && totface != 0) { - printf(" locical error, %d faces and 0 edges\n", totface); + PRINT("ED_mesh_validate: verts(%d), edges(%d), faces(%d)\n", totvert, totedge, totface); + + if(totedge == 0 && totface != 0) { + PRINT(" locical error, %d faces and 0 edges\n", totface); + do_edge_recalc= TRUE; } - for(i=0, med=medges; iv1 == med->v2) { - printf(" edge %d: has matching verts, both %d\n", i, med->v1); + PRINT(" edge %d: has matching verts, both %d\n", i, med->v1); + remove= do_fixes; } - if(med->v1 < 0 || med->v1 >= totvert) { - printf(" edge %d: v1 index out of range, %d\n", i, med->v1); + if(med->v1 >= totvert) { + PRINT(" edge %d: v1 index out of range, %d\n", i, med->v1); + remove= do_fixes; } - if(med->v2 < 0 || med->v2 >= totvert) { - printf(" edge %d: v2 index out of range, %d\n", i, med->v2); + if(med->v2 >= totvert) { + PRINT(" edge %d: v2 index out of range, %d\n", i, med->v2); + remove= do_fixes; } if(BLI_edgehash_haskey(edge_hash, med->v1, med->v2)) { - printf(" edge %d: is a duplicate of, %d\n", i, GET_INT_FROM_POINTER(BLI_edgehash_lookup(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))); + remove= do_fixes; } - BLI_edgehash_insert(edge_hash, med->v1, med->v2, SET_INT_IN_POINTER(i)); + if(remove == FALSE){ + BLI_edgehash_insert(edge_hash, med->v1, med->v2, SET_INT_IN_POINTER(i)); + } + else { + REMOVE_EDGE_TAG(med); + } } for(i=0, mf=mfaces; iv4 ? 3:2; do { fverts[fidx]= *(&mf->v1 + fidx); - if(fverts[fidx] < 0 || fverts[fidx] >= totvert) { - printf(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, fverts[fidx]); + if(fverts[fidx] >= totvert) { + PRINT(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, fverts[fidx]); + remove= do_fixes; } } while (fidx--); - if(mf->v4) { - if(mf->v1 == mf->v2) printf(" face %d: verts invalid, v1/v2 both %d\n", i, mf->v1); - if(mf->v1 == mf->v3) printf(" face %d: verts invalid, v1/v3 both %d\n", i, mf->v1); - if(mf->v1 == mf->v4) printf(" face %d: verts invalid, v1/v4 both %d\n", i, mf->v1); + 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->v2 == mf->v3) printf(" face %d: verts invalid, v2/v3 both %d\n", i, mf->v2); - if(mf->v2 == mf->v4) printf(" face %d: verts invalid, v2/v4 both %d\n", i, mf->v2); + 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->v3 == mf->v4) printf(" face %d: verts invalid, v3/v4 both %d\n", i, mf->v3); + if(mf->v3 == mf->v4) { PRINT(" face %d: verts invalid, v3/v4 both %d\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(totedge) { - if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) printf(" face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); - if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) printf(" face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); - if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v4)) printf(" face %d: edge v3/v4 (%d,%d) is missing egde data\n", i, mf->v3, mf->v4); - if(!BLI_edgehash_haskey(edge_hash, mf->v4, mf->v1)) printf(" face %d: edge v4/v1 (%d,%d) is missing egde data\n", i, mf->v4, mf->v1); + if(mf->v2 == mf->v3) { PRINT(" faceT %d: verts invalid, v2/v3 both %d\n", i, mf->v2); remove= do_fixes; } } - /* TODO, avoid double lookop */ - /* - fedges[0]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v1, mf->v2)); - fedges[1]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v2, mf->v3)); - fedges[2]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v3, mf->v4)); - fedges[3]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v4, mf->v1)); - */ - qsort(fverts, 4, sizeof(int), uint_cmp); - } - else { - if(mf->v1 == mf->v2) printf(" face %d: verts invalid, v1/v2 both %d\n", i, mf->v1); - if(mf->v1 == mf->v3) printf(" face %d: verts invalid, v1/v3 both %d\n", i, mf->v1); - if(mf->v2 == mf->v3) printf(" face %d: verts invalid, v2/v3 both %d\n", i, mf->v2); + 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; } + } + 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(totedge) { - if(!BLI_edgehash_haskey(edge_hash, mf->v1, mf->v2)) printf(" face %d: edge v1/v2 (%d,%d) is missing egde data\n", i, mf->v1, mf->v2); - if(!BLI_edgehash_haskey(edge_hash, mf->v2, mf->v3)) printf(" face %d: edge v2/v3 (%d,%d) is missing egde data\n", i, mf->v2, mf->v3); - if(!BLI_edgehash_haskey(edge_hash, mf->v3, mf->v1)) printf(" face %d: edge v3/v1 (%d,%d) is missing egde data\n", i, mf->v3, mf->v1); - } - /* TODO, avoid double lookop */ - /* - fedges[0]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v1, mf->v2)); - fedges[1]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v2, mf->v3)); - fedges[2]= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, mf->v3, mf->v1)); - */ - qsort(fverts, 3, sizeof(int), uint_cmp); - } + search_faces[totsearchface].index = i; - search_faces[i].index = i; + if(mf->v4) { + qsort(fverts, 4, sizeof(unsigned int), uint_cmp); + search_faces[i].v[0] = fverts[0]; + search_faces[i].v[1] = fverts[1]; + search_faces[i].v[2] = fverts[2]; + search_faces[i].v[3] = fverts[3]; + } + else { + qsort(fverts, 3, sizeof(unsigned int), uint_cmp); + search_faces[i].v[0] = fverts[0]; + search_faces[i].v[1] = fverts[1]; + search_faces[i].v[2] = fverts[2]; + search_faces[i].v[3] = UINT_MAX; + } - if(mf->v4) { - search_faces[i].v[0] = fverts[0]; - search_faces[i].v[1] = fverts[1]; - search_faces[i].v[2] = fverts[2]; - search_faces[i].v[3] = fverts[3]; + totsearchface++; + } } - else { - search_faces[i].v[0] = fverts[0]; - search_faces[i].v[1] = fverts[1]; - search_faces[i].v[2] = fverts[2]; - search_faces[i].v[3] = UINT_MAX; + if(remove) { + REMOVE_FACE_TAG(mf); } } - qsort(search_faces, totface, sizeof(SearchFace), search_face_cmp); + qsort(search_faces, totsearchface, sizeof(SearchFace), search_face_cmp); sf= search_faces; sf_prev= sf; sf++; - for(i=1; iv, sf_prev->v, sizeof(sf_prev->v)) == 0) { /* slow, could be smarter here */ MFace *mf= mfaces + sf->index; MFace *mf_prev= mfaces + sf_prev->index; - int size_expect, size_found; - - EdgeHash *eh_tmp= BLI_edgehash_new(); - if(mf->v4) { - BLI_edgehash_insert(eh_tmp, mf->v1, mf->v2, NULL); - BLI_edgehash_insert(eh_tmp, mf->v2, mf->v3, NULL); - BLI_edgehash_insert(eh_tmp, mf->v3, mf->v4, NULL); - BLI_edgehash_insert(eh_tmp, mf->v4, mf->v1, NULL); - BLI_edgehash_insert(eh_tmp, mf_prev->v1, mf_prev->v2, NULL); - BLI_edgehash_insert(eh_tmp, mf_prev->v2, mf_prev->v3, NULL); - BLI_edgehash_insert(eh_tmp, mf_prev->v3, mf_prev->v4, NULL); - BLI_edgehash_insert(eh_tmp, mf_prev->v4, mf_prev->v1, NULL); + EdgeStore es[4]; + EdgeStore es_prev[4]; - size_expect= 4; + if(mf->v4) { + edge_store_from_mface_quad(es, mf); + edge_store_from_mface_quad(es_prev, mf_prev); + + if( + ELEM4(es[0].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval, es_prev[3].edval) && + ELEM4(es[1].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval, es_prev[3].edval) && + ELEM4(es[2].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval, es_prev[3].edval) && + ELEM4(es[3].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval, es_prev[3].edval) + ) { + PRINT(" face %d & %d: are duplicates ", sf->index, sf_prev->index); + PRINT("(%d,%d,%d,%d) ", mf->v1, mf->v2, mf->v3, mf->v4); + PRINT("(%d,%d,%d,%d)\n", mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4); + remove= do_fixes; + } } else { - BLI_edgehash_insert(eh_tmp, mf->v1, mf->v2, NULL); - BLI_edgehash_insert(eh_tmp, mf->v2, mf->v3, NULL); - BLI_edgehash_insert(eh_tmp, mf->v3, mf->v1, NULL); - - BLI_edgehash_insert(eh_tmp, mf_prev->v1, mf_prev->v2, NULL); - BLI_edgehash_insert(eh_tmp, mf_prev->v2, mf_prev->v3, NULL); - BLI_edgehash_insert(eh_tmp, mf_prev->v3, mf_prev->v1, NULL); - - size_expect= 3; - } - - size_found= BLI_edgehash_size(eh_tmp); - BLI_edgehash_free(eh_tmp, NULL); - - if(size_found != size_expect) { - printf(" face %d & %d: are duplicates ", sf->index, sf_prev->index); - if(mf->v4) { - printf("(%d,%d,%d,%d) ", mf->v1, mf->v2, mf->v3, mf->v4); - printf("(%d,%d,%d,%d)\n", mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4); - } - else { - printf("(%d,%d,%d) ", mf->v1, mf->v2, mf->v3); - printf("(%d,%d,%d)\n", mf_prev->v1, mf_prev->v2, mf_prev->v3); + edge_store_from_mface_tri(es, mf); + edge_store_from_mface_tri(es_prev, mf); + if( + ELEM3(es[0].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval) && + ELEM3(es[1].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval) && + ELEM3(es[2].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval) + ) { + PRINT(" face %d & %d: are duplicates ", sf->index, sf_prev->index); + PRINT("(%d,%d,%d) ", mf->v1, mf->v2, mf->v3); + PRINT("(%d,%d,%d)\n", mf_prev->v1, mf_prev->v2, mf_prev->v3); + remove= do_fixes; } } } + + if(remove) { + REMOVE_FACE_TAG(mf); + /* keep sf_prev */ + } + else { + sf_prev= sf; + } } BLI_edgehash_free(edge_hash, NULL); MEM_freeN(search_faces); - printf("BKE_mesh_validate: finished\n\n"); + PRINT("BKE_mesh_validate: finished\n\n"); + +# undef PRINT +# undef REMOVE_EDGE_TAG +# undef REMOVE_FACE_TAG + + if(me) { + if(do_face_free) { + mesh_strip_loose_faces(me); + } + + if (do_edge_free) { + mesh_strip_loose_edges(me); + } + + if(do_fixes && do_edge_recalc) { + BKE_mesh_calc_edges(me, TRUE); + } + } } void BKE_mesh_validate(Mesh *me) { printf("MESH: %s\n", me->id.name+2); - BKE_mesh_validate_arrays(me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface); + BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, TRUE, TRUE); } void BKE_mesh_validate_dm(DerivedMesh *dm) { - BKE_mesh_validate_arrays(dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm)); + BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm), TRUE, FALSE); +} + + +void BKE_mesh_calc_edges(Mesh *mesh, int update) +{ + CustomData edata; + EdgeHashIterator *ehi; + MFace *mf = mesh->mface; + MEdge *med, *med_orig; + EdgeHash *eh = BLI_edgehash_new(); + int i, totedge, totface = mesh->totface; + + if(mesh->totedge==0) + update= 0; + + if(update) { + /* assume existing edges are valid + * useful when adding more faces and generating edges from them */ + med= mesh->medge; + for(i= 0; itotedge; i++, med++) + BLI_edgehash_insert(eh, med->v1, med->v2, med); + } + + for (i = 0; i < totface; i++, mf++) { + if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) + BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); + if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) + BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); + + if (mf->v4) { + if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) + BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); + if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) + BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); + } else { + if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) + BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); + } + } + + totedge = BLI_edgehash_size(eh); + + /* write new edges into a temporary CustomData */ + memset(&edata, 0, sizeof(edata)); + CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); + + ehi = BLI_edgehashIterator_new(eh); + med = CustomData_get_layer(&edata, CD_MEDGE); + for(i = 0; !BLI_edgehashIterator_isDone(ehi); + BLI_edgehashIterator_step(ehi), ++i, ++med) { + + if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) { + *med= *med_orig; /* copy from the original */ + } else { + BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); + med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */ + } + } + BLI_edgehashIterator_free(ehi); + + /* free old CustomData and assign new one */ + CustomData_free(&mesh->edata, mesh->totedge); + mesh->edata = edata; + mesh->totedge = totedge; + + mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE); + + BLI_edgehash_free(eh, NULL); } -- cgit v1.2.3 From 30ada8fdd3b847844e49f0a0cce0124460821b31 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Feb 2011 04:48:49 +0000 Subject: fix [#26003] Twice applied modifier with Convert to mesh with several multi-user objects convert_exec could do with a re-write, getting quite confusing. update md5's for ctest results and some renaming in mesh_validate code. --- source/blender/blenkernel/intern/mesh_validate.c | 77 ++++++++++++------------ 1 file changed, 38 insertions(+), 39 deletions(-) (limited to 'source/blender/blenkernel/intern/mesh_validate.c') diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 84b7307b820..e45d3a48047 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -44,15 +44,15 @@ #define SELECT 1 -typedef struct SearchFace { +typedef struct SortFace { unsigned int v[4]; unsigned int index; -} SearchFace; +} SortFace; typedef union { uint32_t verts[2]; int64_t edval; -} EdgeStore; +} EdgeUUID; static void edge_store_assign(uint32_t verts[2], const uint32_t v1, const uint32_t v2) { @@ -66,7 +66,7 @@ static void edge_store_assign(uint32_t verts[2], const uint32_t v1, const uint3 } } -static void edge_store_from_mface_quad(EdgeStore es[3], MFace *mf) +static void edge_store_from_mface_quad(EdgeUUID es[3], MFace *mf) { edge_store_assign(es[0].verts, mf->v1, mf->v2); edge_store_assign(es[1].verts, mf->v2, mf->v3); @@ -74,7 +74,7 @@ static void edge_store_from_mface_quad(EdgeStore es[3], MFace *mf) edge_store_assign(es[2].verts, mf->v4, mf->v1); } -static void edge_store_from_mface_tri(EdgeStore es[3], MFace *mf) +static void edge_store_from_mface_tri(EdgeUUID es[3], MFace *mf) { edge_store_assign(es[0].verts, mf->v1, mf->v2); edge_store_assign(es[1].verts, mf->v2, mf->v3); @@ -92,7 +92,7 @@ static int uint_cmp(const void *v1, const void *v2) static int search_face_cmp(const void *v1, const void *v2) { - const SearchFace *sfa= v1, *sfb= v2; + const SortFace *sfa= v1, *sfb= v2; if (sfa->v[0] > sfb->v[0]) return 1; else if (sfa->v[0] < sfb->v[0]) return -1; @@ -127,10 +127,10 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg EdgeHash *edge_hash = BLI_edgehash_new(); - SearchFace *search_faces= MEM_callocN(sizeof(SearchFace) * totface, "search faces"); - SearchFace *sf; - SearchFace *sf_prev; - int totsearchface= 0; + SortFace *sort_faces= MEM_callocN(sizeof(SortFace) * totface, "search faces"); + SortFace *sf; + SortFace *sf_prev; + int totsortface= 0; BLI_assert(!(do_fixes && me == NULL)); @@ -217,24 +217,24 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg } } - search_faces[totsearchface].index = i; + sort_faces[totsortface].index = i; if(mf->v4) { qsort(fverts, 4, sizeof(unsigned int), uint_cmp); - search_faces[i].v[0] = fverts[0]; - search_faces[i].v[1] = fverts[1]; - search_faces[i].v[2] = fverts[2]; - search_faces[i].v[3] = fverts[3]; + sort_faces[i].v[0] = fverts[0]; + sort_faces[i].v[1] = fverts[1]; + sort_faces[i].v[2] = fverts[2]; + sort_faces[i].v[3] = fverts[3]; } else { qsort(fverts, 3, sizeof(unsigned int), uint_cmp); - search_faces[i].v[0] = fverts[0]; - search_faces[i].v[1] = fverts[1]; - search_faces[i].v[2] = fverts[2]; - search_faces[i].v[3] = UINT_MAX; + sort_faces[i].v[0] = fverts[0]; + sort_faces[i].v[1] = fverts[1]; + sort_faces[i].v[2] = fverts[2]; + sort_faces[i].v[3] = UINT_MAX; } - totsearchface++; + totsortface++; } } if(remove) { @@ -242,13 +242,13 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg } } - qsort(search_faces, totsearchface, sizeof(SearchFace), search_face_cmp); + qsort(sort_faces, totsortface, sizeof(SortFace), search_face_cmp); - sf= search_faces; + sf= sort_faces; sf_prev= sf; sf++; - for(i=1; iv, sf_prev->v, sizeof(sf_prev->v)) == 0) { @@ -256,18 +256,18 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg MFace *mf= mfaces + sf->index; MFace *mf_prev= mfaces + sf_prev->index; - EdgeStore es[4]; - EdgeStore es_prev[4]; + EdgeUUID eu[4]; + EdgeUUID eu_prev[4]; if(mf->v4) { - edge_store_from_mface_quad(es, mf); - edge_store_from_mface_quad(es_prev, mf_prev); + edge_store_from_mface_quad(eu, mf); + edge_store_from_mface_quad(eu_prev, mf_prev); if( - ELEM4(es[0].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval, es_prev[3].edval) && - ELEM4(es[1].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval, es_prev[3].edval) && - ELEM4(es[2].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval, es_prev[3].edval) && - ELEM4(es[3].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval, es_prev[3].edval) + ELEM4(eu[0].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval, eu_prev[3].edval) && + ELEM4(eu[1].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval, eu_prev[3].edval) && + ELEM4(eu[2].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval, eu_prev[3].edval) && + ELEM4(eu[3].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval, eu_prev[3].edval) ) { PRINT(" face %d & %d: are duplicates ", sf->index, sf_prev->index); PRINT("(%d,%d,%d,%d) ", mf->v1, mf->v2, mf->v3, mf->v4); @@ -276,12 +276,12 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg } } else { - edge_store_from_mface_tri(es, mf); - edge_store_from_mface_tri(es_prev, mf); + edge_store_from_mface_tri(eu, mf); + edge_store_from_mface_tri(eu_prev, mf); if( - ELEM3(es[0].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval) && - ELEM3(es[1].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval) && - ELEM3(es[2].edval, es_prev[0].edval, es_prev[1].edval, es_prev[2].edval) + ELEM3(eu[0].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval) && + ELEM3(eu[1].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval) && + ELEM3(eu[2].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval) ) { PRINT(" face %d & %d: are duplicates ", sf->index, sf_prev->index); PRINT("(%d,%d,%d) ", mf->v1, mf->v2, mf->v3); @@ -293,7 +293,7 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg if(remove) { REMOVE_FACE_TAG(mf); - /* keep sf_prev */ + /* keep sf_prev incase next face also matches*/ } else { sf_prev= sf; @@ -301,7 +301,7 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg } BLI_edgehash_free(edge_hash, NULL); - MEM_freeN(search_faces); + MEM_freeN(sort_faces); PRINT("BKE_mesh_validate: finished\n\n"); @@ -335,7 +335,6 @@ void BKE_mesh_validate_dm(DerivedMesh *dm) BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm), TRUE, FALSE); } - void BKE_mesh_calc_edges(Mesh *mesh, int update) { CustomData edata; -- cgit v1.2.3 From 264c8c21623c3b011494e169f0571c410331e553 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Feb 2011 09:29:31 +0000 Subject: mesh.validate() now returns True if any corrections were made. tested that correcting invalid meshes works by generating random meshes and checking that only the first call to mesh.validate() makes changes. found 2 bugs in mesh validation. - face sorting array wasn't assigned correct indices. - removing invalid edges used wrong comparison. --- source/blender/blenkernel/intern/mesh_validate.c | 38 ++++++++++-------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'source/blender/blenkernel/intern/mesh_validate.c') diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index e45d3a48047..35a23a17115 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -109,7 +109,7 @@ static int search_face_cmp(const void *v1, const void *v2) return 0; } -void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge *medges, int totedge, MFace *mfaces, int totface, const short do_verbose, const short do_fixes) +int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge *medges, int totedge, MFace *mfaces, 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; } @@ -169,17 +169,15 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg } } - for(i=0, mf=mfaces; iv4 ? 3:2; do { - fverts[fidx]= *(&mf->v1 + fidx); - if(fverts[fidx] >= totvert) { - PRINT(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, fverts[fidx]); + sf->v[fidx]= *(&mf->v1 + fidx); + if(sf->v[fidx] >= totvert) { + PRINT(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, sf->v[fidx]); remove= do_fixes; } } while (fidx--); @@ -220,21 +218,15 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg sort_faces[totsortface].index = i; if(mf->v4) { - qsort(fverts, 4, sizeof(unsigned int), uint_cmp); - sort_faces[i].v[0] = fverts[0]; - sort_faces[i].v[1] = fverts[1]; - sort_faces[i].v[2] = fverts[2]; - sort_faces[i].v[3] = fverts[3]; + qsort(sf->v, 4, sizeof(unsigned int), uint_cmp); } else { - qsort(fverts, 3, sizeof(unsigned int), uint_cmp); - sort_faces[i].v[0] = fverts[0]; - sort_faces[i].v[1] = fverts[1]; - sort_faces[i].v[2] = fverts[2]; - sort_faces[i].v[3] = UINT_MAX; + qsort(sf->v, 3, sizeof(unsigned int), uint_cmp); + sf->v[3] = UINT_MAX; } totsortface++; + sf++; } } if(remove) { @@ -322,17 +314,19 @@ void BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdg BKE_mesh_calc_edges(me, TRUE); } } + + return (do_face_free || do_edge_free || do_edge_recalc); } -void BKE_mesh_validate(Mesh *me) +int BKE_mesh_validate(Mesh *me, int do_verbose) { printf("MESH: %s\n", me->id.name+2); - BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, TRUE, TRUE); + return BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, do_verbose, TRUE); } -void BKE_mesh_validate_dm(DerivedMesh *dm) +int BKE_mesh_validate_dm(DerivedMesh *dm) { - BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm), TRUE, FALSE); + return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm), TRUE, FALSE); } void BKE_mesh_calc_edges(Mesh *mesh, int update) -- cgit v1.2.3 From 7daabec53482a5b0700f19a0d03ed7ae60d1e1a2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Feb 2011 12:34:52 +0000 Subject: mesh validation: bugfix for removing doubles, another fix coming... --- source/blender/blenkernel/intern/mesh_validate.c | 31 ++++++++++++++---------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'source/blender/blenkernel/intern/mesh_validate.c') diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 35a23a17115..5d8a2bdeb72 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -66,12 +66,12 @@ static void edge_store_assign(uint32_t verts[2], const uint32_t v1, const uint3 } } -static void edge_store_from_mface_quad(EdgeUUID es[3], MFace *mf) +static void edge_store_from_mface_quad(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); edge_store_assign(es[2].verts, mf->v3, mf->v4); - edge_store_assign(es[2].verts, mf->v4, mf->v1); + edge_store_assign(es[3].verts, mf->v4, mf->v1); } static void edge_store_from_mface_tri(EdgeUUID es[3], MFace *mf) @@ -83,7 +83,8 @@ static void edge_store_from_mface_tri(EdgeUUID es[3], MFace *mf) static int uint_cmp(const void *v1, const void *v2) { - const unsigned int x1= GET_INT_FROM_POINTER(v1), x2= GET_INT_FROM_POINTER(v2); + const unsigned int x1= *(const unsigned int *)v1; + const unsigned int x2= *(const unsigned int *)v2; if( x1 > x2 ) return 1; else if( x1 < x2 ) return -1; @@ -97,16 +98,19 @@ static int search_face_cmp(const void *v1, const void *v2) if (sfa->v[0] > sfb->v[0]) return 1; else if (sfa->v[0] < sfb->v[0]) return -1; - if (sfa->v[1] > sfb->v[1]) return 1; + else if (sfa->v[1] > sfb->v[1]) return 1; else if (sfa->v[1] < sfb->v[1]) return -1; - if (sfa->v[2] > sfb->v[2]) return 1; + else if (sfa->v[2] > sfb->v[2]) return 1; else if (sfa->v[2] < sfb->v[2]) return -1; - if (sfa->v[3] > sfb->v[3]) return 1; + else if (sfa->v[3] > sfb->v[3]) return 1; else if (sfa->v[3] < sfb->v[3]) return -1; - return 0; +// else if (sfb->index > sfa->index) return 1; +// else if (sfb->index < sfa->index) return -1; + else return 0; + } int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge *medges, int totedge, MFace *mfaces, int totface, const short do_verbose, const short do_fixes) @@ -118,6 +122,7 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge // MVert *mv; MEdge *med; MFace *mf; + MFace *mf_prev; int i; int do_face_free= FALSE; @@ -175,7 +180,7 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge fidx = mf->v4 ? 3:2; do { - sf->v[fidx]= *(&mf->v1 + fidx); + sf->v[fidx]= *(&(mf->v1) + fidx); if(sf->v[fidx] >= totvert) { PRINT(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, sf->v[fidx]); remove= do_fixes; @@ -215,7 +220,7 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge } } - sort_faces[totsortface].index = i; + sf->index = i; if(mf->v4) { qsort(sf->v, 4, sizeof(unsigned int), uint_cmp); @@ -245,12 +250,12 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge /* on a valid mesh, code below will never run */ if(memcmp(sf->v, sf_prev->v, sizeof(sf_prev->v)) == 0) { /* slow, could be smarter here */ - MFace *mf= mfaces + sf->index; - MFace *mf_prev= mfaces + sf_prev->index; - EdgeUUID eu[4]; EdgeUUID eu_prev[4]; + mf= mfaces + sf->index; + mf_prev= mfaces + sf_prev->index; + if(mf->v4) { edge_store_from_mface_quad(eu, mf); edge_store_from_mface_quad(eu_prev, mf_prev); @@ -269,7 +274,7 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge } else { edge_store_from_mface_tri(eu, mf); - edge_store_from_mface_tri(eu_prev, mf); + edge_store_from_mface_tri(eu_prev, mf_prev); if( ELEM3(eu[0].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval) && ELEM3(eu[1].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval) && -- cgit v1.2.3 From 1817a045b47985e9edb3ccdbbfc5ea9f79c8d363 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Feb 2011 14:13:13 +0000 Subject: mesh validation remove duplicate faces didn't always work, now it _should_ all work correctly. --- source/blender/blenkernel/intern/mesh_validate.c | 103 +++++++++-------------- 1 file changed, 40 insertions(+), 63 deletions(-) (limited to 'source/blender/blenkernel/intern/mesh_validate.c') diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 5d8a2bdeb72..e5aacdf2cf9 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -44,16 +44,17 @@ #define SELECT 1 -typedef struct SortFace { - unsigned int v[4]; - unsigned int index; -} SortFace; - typedef union { uint32_t verts[2]; int64_t edval; } EdgeUUID; +typedef struct SortFace { +// unsigned int v[4]; + EdgeUUID es[4]; + unsigned int index; +} SortFace; + static void edge_store_assign(uint32_t verts[2], const uint32_t v1, const uint32_t v2) { if(v1 < v2) { @@ -79,12 +80,13 @@ static void edge_store_from_mface_tri(EdgeUUID es[3], MFace *mf) edge_store_assign(es[0].verts, mf->v1, mf->v2); edge_store_assign(es[1].verts, mf->v2, mf->v3); edge_store_assign(es[2].verts, mf->v3, mf->v1); + es[3].verts[0] = es[3].verts[1] = UINT_MAX; } -static int uint_cmp(const void *v1, const void *v2) +static int int64_cmp(const void *v1, const void *v2) { - const unsigned int x1= *(const unsigned int *)v1; - const unsigned int x2= *(const unsigned int *)v2; + const int64_t x1= *(const int64_t *)v1; + const int64_t x2= *(const int64_t *)v2; if( x1 > x2 ) return 1; else if( x1 < x2 ) return -1; @@ -95,21 +97,18 @@ static int search_face_cmp(const void *v1, const void *v2) { const SortFace *sfa= v1, *sfb= v2; - if (sfa->v[0] > sfb->v[0]) return 1; - else if (sfa->v[0] < sfb->v[0]) return -1; + if (sfa->es[0].edval > sfb->es[0].edval) return 1; + else if (sfa->es[0].edval < sfb->es[0].edval) return -1; - else if (sfa->v[1] > sfb->v[1]) return 1; - else if (sfa->v[1] < sfb->v[1]) return -1; + else if (sfa->es[1].edval > sfb->es[1].edval) return 1; + else if (sfa->es[1].edval < sfb->es[1].edval) return -1; - else if (sfa->v[2] > sfb->v[2]) return 1; - else if (sfa->v[2] < sfb->v[2]) return -1; + else if (sfa->es[2].edval > sfb->es[2].edval) return 1; + else if (sfa->es[2].edval < sfb->es[2].edval) return -1; - else if (sfa->v[3] > sfb->v[3]) return 1; - else if (sfa->v[3] < sfb->v[3]) return -1; - -// else if (sfb->index > sfa->index) return 1; -// else if (sfb->index < sfa->index) return -1; - else return 0; + else if (sfa->es[3].edval > sfb->es[3].edval) return 1; + else if (sfa->es[3].edval < sfb->es[3].edval) return -1; + else return 0; } @@ -177,12 +176,13 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge for(i=0, mf=mfaces, sf=sort_faces; iv4 ? 3:2; do { - sf->v[fidx]= *(&(mf->v1) + fidx); - if(sf->v[fidx] >= totvert) { - PRINT(" face %d: 'v%d' index out of range, %d\n", i, fidx + 1, sf->v[fidx]); + 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]); remove= do_fixes; } } while (fidx--); @@ -223,11 +223,13 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge sf->index = i; if(mf->v4) { - qsort(sf->v, 4, sizeof(unsigned int), uint_cmp); + edge_store_from_mface_quad(sf->es, mf); + + qsort(sf->es, 4, sizeof(int64_t), int64_cmp); } else { - qsort(sf->v, 3, sizeof(unsigned int), uint_cmp); - sf->v[3] = UINT_MAX; + edge_store_from_mface_tri(sf->es, mf); + qsort(sf->es, 3, sizeof(int64_t), int64_cmp); } totsortface++; @@ -248,53 +250,28 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), int totvert, MEdge for(i=1; iv, sf_prev->v, sizeof(sf_prev->v)) == 0) { - /* slow, could be smarter here */ - EdgeUUID eu[4]; - EdgeUUID eu_prev[4]; - + if(memcmp(sf->es, sf_prev->es, sizeof(sf_prev->es)) == 0) { mf= mfaces + sf->index; - mf_prev= mfaces + sf_prev->index; - if(mf->v4) { - edge_store_from_mface_quad(eu, mf); - edge_store_from_mface_quad(eu_prev, mf_prev); - - if( - ELEM4(eu[0].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval, eu_prev[3].edval) && - ELEM4(eu[1].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval, eu_prev[3].edval) && - ELEM4(eu[2].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval, eu_prev[3].edval) && - ELEM4(eu[3].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval, eu_prev[3].edval) - ) { - PRINT(" face %d & %d: are duplicates ", sf->index, sf_prev->index); - PRINT("(%d,%d,%d,%d) ", mf->v1, mf->v2, mf->v3, mf->v4); - PRINT("(%d,%d,%d,%d)\n", mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4); - remove= do_fixes; + 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); } - } - else { - edge_store_from_mface_tri(eu, mf); - edge_store_from_mface_tri(eu_prev, mf_prev); - if( - ELEM3(eu[0].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval) && - ELEM3(eu[1].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval) && - ELEM3(eu[2].edval, eu_prev[0].edval, eu_prev[1].edval, eu_prev[2].edval) - ) { - PRINT(" face %d & %d: are duplicates ", sf->index, sf_prev->index); - PRINT("(%d,%d,%d) ", mf->v1, mf->v2, mf->v3); - PRINT("(%d,%d,%d)\n", mf_prev->v1, mf_prev->v2, mf_prev->v3); - remove= do_fixes; + 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); } } - } - if(remove) { - REMOVE_FACE_TAG(mf); - /* keep sf_prev incase next face also matches*/ + remove= do_fixes; } else { sf_prev= sf; } + + if(remove) { + REMOVE_FACE_TAG(mf); + } } BLI_edgehash_free(edge_hash, NULL); -- cgit v1.2.3 From 5b607701a7541c328cc058e10bd7a8c6d0c998ab Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 23 Feb 2011 10:52:22 +0000 Subject: doxygen: prevent GPL license block from being parsed as doxygen comment. --- source/blender/blenkernel/intern/mesh_validate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/mesh_validate.c') diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index e5aacdf2cf9..8b0b7a041dc 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** -- cgit v1.2.3