diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-08-06 03:40:21 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-08-06 03:40:21 +0400 |
commit | deddb90a41e8a4adf5d601af4fabda1ddcff82b9 (patch) | |
tree | be9649b0dc3c1f2bba9dd8b058b0b9f4b34bd475 | |
parent | 4f71435bbf273d9508bd0980bda53469cb26dad0 (diff) |
bugfix [#23179] Screw Modifier looses VGroups
- flip option now flips faces rather then flipping loop order. Now it can copy vertex data in chunks the size of the original vertex count.
- converted macro's to static func's and some general cleanup.
-rw-r--r-- | source/blender/modifiers/intern/MOD_screw.c | 223 |
1 files changed, 123 insertions, 100 deletions
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index cbd9ae42a26..e525e782550 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -61,39 +61,45 @@ typedef struct ScrewVertIter { MEdge *e; } ScrewVertIter; -#define ScrewVertIter_INIT(iter, array, v_init, dir)\ - iter.v_array = array;\ - iter.v = v_init;\ - if (v_init>=0) {\ - iter.v_poin = &array[v_init];\ - iter.v_other = iter.v_poin->v[dir];\ - if (dir)\ - iter.e = iter.v_poin->e[0];\ - else\ - iter.e = iter.v_poin->e[1];\ - } else {\ - iter.v_poin= NULL;\ - iter.e= NULL;\ + +static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, int v_init, int dir) +{ + iter->v_array = array; + iter->v = v_init; + + if (v_init >= 0) { + iter->v_poin = &array[v_init]; + iter->v_other = iter->v_poin->v[dir]; + iter->e = iter->v_poin->e[!dir]; + } + else { + iter->v_poin= NULL; + iter->e= NULL; } +} -#define ScrewVertIter_NEXT(iter)\ - if (iter.v_poin->v[0] == iter.v_other) {\ - iter.v_other= iter.v;\ - iter.v= iter.v_poin->v[1];\ - } else if (iter.v_poin->v[1] == iter.v_other) {\ - iter.v_other= iter.v;\ - iter.v= iter.v_poin->v[0];\ - }\ - if (iter.v >=0) {\ - iter.v_poin= &iter.v_array[iter.v];\ - if ( iter.v_poin->e[0] != iter.e ) iter.e= iter.v_poin->e[0];\ - else iter.e= iter.v_poin->e[1];\ - } else {\ - iter.e= NULL;\ - iter.v_poin= NULL;\ +static void screwvert_iter_step(ScrewVertIter *iter) +{ + if (iter->v_poin->v[0] == iter->v_other) { + iter->v_other= iter->v; + iter->v= iter->v_poin->v[1]; } - + else if (iter->v_poin->v[1] == iter->v_other) { + iter->v_other= iter->v; + iter->v= iter->v_poin->v[0]; + } + if (iter->v >= 0) { + iter->v_poin= &iter->v_array[iter->v]; + iter->e= iter->v_poin->e[(iter->v_poin->e[0] == iter->e)]; + } + else { + iter->e= NULL; + iter->v_poin= NULL; + } +} + + static void initData(ModifierData *md) { ScrewModifierData *ltmd= (ScrewModifierData*) md; @@ -131,9 +137,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, int *origindex; int mface_index=0; + int step; int i, j; int i1,i2; - int steps= ltmd->steps; + int step_tot= ltmd->steps; + const int do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0; int maxVerts=0, maxEdges=0, maxFaces=0; int totvert= dm->getNumVerts(dm); int totedge= dm->getNumEdges(dm); @@ -167,7 +175,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (!totvert) return CDDM_from_template(dm, 0, 0, 0); - steps= useRenderParams ? ltmd->render_steps : ltmd->steps; + step_tot= useRenderParams ? ltmd->render_steps : ltmd->steps; switch(ltmd->axis) { case 0: @@ -261,30 +269,30 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, screw_ofs *= ltmd->iter; /* multiplying the steps is a bit tricky, this works best */ - steps = ((steps + 1) * ltmd->iter) - (ltmd->iter - 1); + step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1); /* will the screw be closed? * Note! smaller then FLT_EPSILON*100 gives problems with float precission so its never closed. */ if (fabs(screw_ofs) <= (FLT_EPSILON*100) && fabs(fabs(angle) - (M_PI * 2)) <= (FLT_EPSILON*100)) { close= 1; - steps--; - if(steps < 2) steps= 2; + step_tot--; + if(step_tot < 2) step_tot= 2; - maxVerts = totvert * steps; /* -1 because we're joining back up */ - maxEdges = (totvert * steps) + /* these are the edges between new verts */ - (totedge * steps); /* -1 because vert edges join */ - maxFaces = totedge * steps; + maxVerts = totvert * step_tot; /* -1 because we're joining back up */ + maxEdges = (totvert * step_tot) + /* these are the edges between new verts */ + (totedge * step_tot); /* -1 because vert edges join */ + maxFaces = totedge * step_tot; screw_ofs= 0.0f; } else { close= 0; - if(steps < 2) steps= 2; + if(step_tot < 2) step_tot= 2; - maxVerts = totvert * steps; /* -1 because we're joining back up */ - maxEdges = (totvert * (steps-1)) + /* these are the edges between new verts */ - (totedge * steps); /* -1 because vert edges join */ - maxFaces = totedge * (steps-1); + maxVerts = totvert * step_tot; /* -1 because we're joining back up */ + maxEdges = (totvert * (step_tot-1)) + /* these are the edges between new verts */ + (totedge * step_tot); /* -1 because vert edges join */ + maxFaces = totedge * (step_tot-1); } result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces); @@ -398,11 +406,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, for (i=0; i<totedge; i++, med_new++) { vc= &vert_connect[med_new->v1]; - if (vc->v[0]==-1) { /* unused */ + if (vc->v[0] == -1) { /* unused */ vc->v[0]= med_new->v2; vc->e[0]= med_new; } - else if (vc->v[1]==-1) { + else if (vc->v[1] == -1) { vc->v[1]= med_new->v2; vc->e[1]= med_new; } @@ -413,11 +421,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, vc= &vert_connect[med_new->v2]; /* same as above but swap v1/2 */ - if (vc->v[0]==-1) { /* unused */ + if (vc->v[0] == -1) { /* unused */ vc->v[0]= med_new->v1; vc->e[0]= med_new; } - else if (vc->v[1]==-1) { + else if (vc->v[1] == -1) { vc->v[1]= med_new->v1; vc->e[1]= med_new; } @@ -429,7 +437,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* find the first vert */ vc= vert_connect; for (i=0; i < totvert; i++, vc++) { - int VBEST=-1, ed_loop_closed=0; /* vert and vert new */ + int v_best=-1, ed_loop_closed=0; /* vert and vert new */ int ed_loop_flip; float fl= -1.0f; ScrewVertIter lt_iter; @@ -437,14 +445,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* Now do search for connected verts, order all edges and flip them * so resulting faces are flipped the right way */ vc_tot_linked= 0; /* count the number of linked verts for this loop */ - if (vc->flag==0) { + if (vc->flag == 0) { /*printf("Loop on connected vert: %i\n", i);*/ for(j=0; j<2; j++) { /*printf("\tSide: %i\n", j);*/ - ScrewVertIter_INIT(lt_iter, vert_connect, i, j); - if (j==1) { - ScrewVertIter_NEXT(lt_iter); + screwvert_iter_init(<_iter, vert_connect, i, j); + if (j == 1) { + screwvert_iter_step(<_iter); } while (lt_iter.v_poin) { /*printf("\t\tVERT: %i\n", lt_iter.v);*/ @@ -459,10 +467,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/ if (fl <= lt_iter.v_poin->dist) { fl= lt_iter.v_poin->dist; - VBEST= lt_iter.v; - /*printf("\t\t\tVERT BEST: %i\n", VBEST);*/ + v_best= lt_iter.v; + /*printf("\t\t\tVERT BEST: %i\n", v_best);*/ } - ScrewVertIter_NEXT(lt_iter); + screwvert_iter_step(<_iter); if (!lt_iter.v_poin) { /*printf("\t\t\tFound End Also Num %i\n", j);*/ /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */ @@ -472,14 +480,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } /* now we have a collection of used edges. flip their edges the right way*/ - /*if (VBEST !=-1) - */ + /*if (v_best != -1) - */ /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/ if (vc_tot_linked>1) { float vf_1, vf_2, vf_best; - vc_tmp= &vert_connect[VBEST]; + vc_tmp= &vert_connect[v_best]; tmpf1= vert_connect[vc_tmp->v[0]].co; tmpf2= vert_connect[vc_tmp->v[1]].co; @@ -531,9 +539,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /*printf("flip direction %i\n", ed_loop_flip);*/ - /* switch the flip option if set */ - if (ltmd->flag & MOD_SCREW_NORMAL_FLIP) + /* switch the flip option if set + * note: flip is now done at face level so copying vgroup slizes is easier */ + /* + if (do_flip) ed_loop_flip= !ed_loop_flip; + */ if (angle < 0.0f) ed_loop_flip= !ed_loop_flip; @@ -542,7 +553,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, for(j=ed_loop_closed; j<2; j++) { /*printf("Ordering Side J %i\n", j);*/ - ScrewVertIter_INIT(lt_iter, vert_connect, VBEST, j); + screwvert_iter_init(<_iter, vert_connect, v_best, j); /*printf("\n\nStarting - Loop\n");*/ lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */ @@ -550,7 +561,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* If this is the vert off the best vert and * the best vert has 2 edges connected too it * then swap the flip direction */ - if (j==1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) + if (j == 1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) ed_loop_flip= !ed_loop_flip; while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) { @@ -559,7 +570,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, lt_iter.v_poin->flag= 2; if (lt_iter.e) { if (lt_iter.v == lt_iter.e->v1) { - if (ed_loop_flip==0) { + if (ed_loop_flip == 0) { /*printf("\t\t\tFlipping 0\n");*/ SWAP(int, lt_iter.e->v1, lt_iter.e->v2); }/* else { @@ -567,7 +578,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, }*/ } else if (lt_iter.v == lt_iter.e->v2) { - if (ed_loop_flip==1) { + if (ed_loop_flip == 1) { /*printf("\t\t\tFlipping 1\n");*/ SWAP(int, lt_iter.e->v1, lt_iter.e->v2); }/* else { @@ -579,7 +590,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, }/* else { printf("\t\tNo Edge at this point\n"); }*/ - ScrewVertIter_NEXT(lt_iter); + screwvert_iter_step(<_iter); } } } @@ -591,8 +602,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, * * calculate vertex normals that can be propodated on lathing * use edge connectivity work this out */ - if (vc->v[0]>=0) { - if (vc->v[1]>=0) { + if (vc->v[0] >= 0) { + if (vc->v[1] >= 0) { /* 2 edges connedted */ /* make 2 connecting vert locations relative to the middle vert */ sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co); @@ -647,34 +658,25 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } } else { + mv_orig= mvert_orig; + mv_new= mvert_new; - if (ltmd->flag & MOD_SCREW_NORMAL_FLIP) { - mv_orig= mvert_orig; - mv_new= mvert_new + (totvert-1); - - for (i=0; i < totvert; i++, mv_new--, mv_orig++) { - copy_v3_v3(mv_new->co, mv_orig->co); - } - } - else { - mv_orig= mvert_orig; - mv_new= mvert_new; - - for (i=0; i < totvert; i++, mv_new++, mv_orig++) { - copy_v3_v3(mv_new->co, mv_orig->co); - } + for (i=0; i < totvert; i++, mv_new++, mv_orig++) { + copy_v3_v3(mv_new->co, mv_orig->co); } } /* done with edge connectivity based normal flipping */ + DM_copy_vert_data(dm, result, 0, 0, totvert); /* Add Faces */ - for (i=1; i < steps; i++) { + for (step=1; step < step_tot; step++) { + const int varray_stride= totvert * step; float step_angle; float no_tx[3]; /* Rotation Matrix */ - if (close) step_angle= (angle / steps) * i; - else step_angle= (angle / (steps-1)) * i; + if (close) step_angle= (angle / step_tot) * step; + else step_angle= (angle / (step_tot-1)) * step; if (ltmd->ob_axis) { axis_angle_to_mat3(mat3, axis_vec, step_angle); @@ -687,10 +689,13 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } if(screw_ofs) - madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)i / (float)(steps-1))); + madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)step / (float)(step_tot-1))); + /* copy a slice */ + DM_copy_vert_data(dm, result, 0, varray_stride, totvert); + mv_new_base= mvert_new; - mv_new= &mvert_new[totvert*i]; /* advance to the next slice */ + mv_new= &mvert_new[varray_stride]; /* advance to the next slice */ for (j=0; j<totvert; j++, mv_new_base++, mv_new++) { /* set normal */ @@ -719,7 +724,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } /* add the new edge */ - med_new->v1= j+(i*totvert); + med_new->v1= varray_stride + j; med_new->v2= med_new->v1 - totvert; med_new->flag= ME_EDGEDRAW|ME_EDGERENDER; med_new++; @@ -734,9 +739,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (close) { /* last loop of edges, previous loop dosnt account for the last set of edges */ + const int varray_stride= (step_tot - 1) * totvert; + for (i=0; i<totvert; i++) { med_new->v1= i; - med_new->v2= i+((steps-1)*totvert); + med_new->v2= varray_stride + i; med_new->flag= ME_EDGEDRAW|ME_EDGERENDER; med_new++; } @@ -749,14 +756,22 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* for each edge, make a cylinder of quads */ i1= med_new_firstloop->v1; i2= med_new_firstloop->v2; - - for (j=0; j < steps-1; j++) { + + for (step=0; step < step_tot-1; step++) { /* new face */ - mf_new->v1= i1; - mf_new->v2= i2; - mf_new->v3= i2 + totvert; - mf_new->v4= i1 + totvert; + if(do_flip) { + mf_new->v4= i1; + mf_new->v3= i2; + mf_new->v2= i2 + totvert; + mf_new->v1= i1 + totvert; + } + else { + mf_new->v1= i1; + mf_new->v2= i2; + mf_new->v3= i2 + totvert; + mf_new->v4= i1 + totvert; + } if( !mf_new->v3 || !mf_new->v4 ) { SWAP(int, mf_new->v1, mf_new->v3); @@ -768,7 +783,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, mface_index++; /* new vertical edge */ - if (j) { /* The first set is already dome */ + if (step) { /* The first set is already dome */ med_new->v1= i1; med_new->v2= i2; med_new->flag= med_new_firstloop->flag; @@ -781,10 +796,18 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* close the loop*/ if (close) { - mf_new->v1= i1; - mf_new->v2= i2; - mf_new->v3= med_new_firstloop->v2; - mf_new->v4= med_new_firstloop->v1; + if(do_flip) { + mf_new->v4= i1; + mf_new->v3= i2; + mf_new->v2= med_new_firstloop->v2; + mf_new->v1= med_new_firstloop->v1; + } + else { + mf_new->v1= i1; + mf_new->v2= i2; + mf_new->v3= med_new_firstloop->v2; + mf_new->v4= med_new_firstloop->v1; + } if( !mf_new->v3 || !mf_new->v4 ) { SWAP(int, mf_new->v1, mf_new->v3); @@ -804,7 +827,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, med_new++; } - if((ltmd->flag & MOD_SCREW_NORMAL_CALC)==0) { + if((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) { CDDM_calc_normals(result); } |