Done BMESH_TODO in object/object_vgroup.c (make getSurroundingVerts() use polys/loops instead of tessfaces).

Also done a few optimizations of related code (OBJECT_OT_vertex_group_fix operator).
This commit is contained in:
Bastien Montagne
2012-02-20 22:16:20 +00:00
parent c4e7cc3287
commit 6d3cdbe0e5

View File

@@ -48,6 +48,7 @@
#include "DNA_scene_types.h"
#include "DNA_particle_types.h"
#include "BLI_array.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -748,100 +749,68 @@ static void vgroup_normalize(Object *ob)
}
}
/* This adds the indices of vertices to a list if they are not already present
It returns the number that it added (0-2)
It relies on verts having -1 for unassigned indices
*/
static int tryToAddVerts(int *verts, int length, int a, int b)
{
char containsA = FALSE;
char containsB = FALSE;
int added = 0;
int i;
for(i = 0; i < length && (!containsA || !containsB); i++) {
if(verts[i] == a) {
containsA = TRUE;
} else if(verts[i] == b) {
containsB = TRUE;
} else if(verts[i] == -1) {
if(!containsA) {
verts[i] = a;
containsA = TRUE;
added++;
} else if(!containsB){
verts[i] = b;
containsB = TRUE;
added++;
}
}
}
return added;
}
/* BMESH_TODO - use MPoly's */
/* This finds all of the vertices connected to vert by an edge
and returns an array of indices of size count
count is an int passed by reference so it can be assigned the value of the length here.
*/
/* This finds all of the vertices face-connected to vert by an edge and returns a
* MEM_allocated array of indices of size count.
* count is an int passed by reference so it can be assigned the value of the length here. */
static int* getSurroundingVerts(Mesh *me, int vert, int *count)
{
int length = 0;
int *tverts;
MPoly *mp = me->mpoly;
int i = me->totpoly;
/* Instead of looping twice on all polys and loops, and use a temp array, let's rather
* use a BLI_array, with a reasonable starting/reserved size (typically, there are not
* many vertices face-linked to another one, even 8 might be too high...). */
int *verts = NULL;
MFace *mf = me->mface;
int totface = me->totface;
int found = 0;
int i;
for(i = 0; i < totface; i++, mf++) {
if(vert == mf->v1 || vert == mf->v2 || vert == mf->v3 || (mf->v4 &&vert == mf->v4)) {
length+=2;
}
}
if(!length) {
return NULL;
}
tverts = MEM_mallocN(sizeof(int)*length, "tempSurroundingVerts");
mf = me->mface;
for(i = 0; i < length; i++) {
tverts[i] = -1;
}
for(i = 0; i < totface; i++, mf++) {
int a=-1, b=-1;
if(mf->v1 == vert) {
a = mf->v2;
if(mf->v4) {
b = mf->v4;
} else {
b = mf->v3;
BLI_array_declare(verts);
BLI_array_reserve(verts, 8);
while(i--) {
int j = mp->totloop;
int first_l = mp->totloop - 1;
MLoop *ml = &me->mloop[mp->loopstart];
while(j--) {
/* XXX This assume a vert can only be once in a poly, even though
* it seems logical to me, not totaly sure of that. */
if (ml->v == vert) {
int a, b, k;
if(j == first_l) {
/* We are on the first corner. */
a = ml[1].v;
b = ml[j].v;
}
else if(!j) {
/* We are on the last corner. */
a = (ml-1)->v;
b = me->mloop[mp->loopstart].v;
}
else {
a = (ml-1)->v;
b = (ml+1)->v;
}
/* Append a and b verts to array, if not yet present. */
k = BLI_array_count(verts);
/* XXX Maybe a == b is enough? */
while(k-- && !(a == b && a == -1)) {
if(verts[k] == a)
a = -1;
else if(verts[k] == b)
b = -1;
}
if(a != -1)
BLI_array_append(verts, a);
if(b != -1)
BLI_array_append(verts, b);
/* Vert found in this poly, we can go to next one! */
break;
}
} else if(mf->v2 == vert) {
a = mf->v1;
b = mf->v3;
} else if(mf->v3 == vert) {
a = mf->v2;
if(mf->v4) {
b = mf->v4;
} else {
b = mf->v1;
}
} else if (mf->v4 && mf->v4 == vert){
a = mf->v1;
b = mf->v3;
} else {
continue;
ml++;
}
found += tryToAddVerts(tverts, length, a, b);
mp++;
}
if(found) {
verts = MEM_mallocN(sizeof(int)* found, "surroundingVerts");
for(i = 0; i < found; i++) {
verts[i] = tverts[i];
}
*count = found;
}
MEM_freeN(tverts);
/* Do not free the array! */
*count = BLI_array_count(verts);
return verts;
}
@@ -1087,12 +1056,11 @@ static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength,
Mesh *me = ob->data;
MVert *mvert = me->mvert;
const int use_vert_sel= (me->editflag & ME_EDIT_VERT_SEL) != 0;
int *verts = NULL;
if(!(me->editflag & ME_EDIT_VERT_SEL))
return;
for(i = 0; i < me->totvert && mvert; i++, mvert++) {
if(use_vert_sel && (mvert->flag & SELECT)) {
if(mvert->flag & SELECT) {
int count=0;
if((verts = getSurroundingVerts(me, i, &count))) {
MVert m;
@@ -1100,7 +1068,8 @@ static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength,
int k;
DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
for(k = 0; k < count; k++) {
k = count;
while(k--) {
dm->getVert(dm, verts[k], &m);
p[k] = m;
}