Blender V2.61 - r43446

MOD_screw.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) 2005 by the Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Daniel Dunbar
00022  *                 Ton Roosendaal,
00023  *                 Ben Batt,
00024  *                 Brecht Van Lommel,
00025  *                 Campbell Barton
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  *
00029  */
00030 
00036 /* Screw modifier: revolves the edges about an axis */
00037 
00038 #include "DNA_meshdata_types.h"
00039 #include "DNA_object_types.h"
00040 
00041 #include "BLI_math.h"
00042 #include "BLI_utildefines.h"
00043 
00044 
00045 #include "BKE_cdderivedmesh.h"
00046 
00047 #include "depsgraph_private.h"
00048 #include "MOD_modifiertypes.h"
00049 #include "MEM_guardedalloc.h"
00050 
00051 /* used for gathering edge connectivity */
00052 typedef struct ScrewVertConnect {
00053     float dist;  /* distance from the center axis */
00054     float co[3]; /* loaction relative to the transformed axis */
00055     float no[3]; /* calc normal of the vertex */
00056     int v[2]; /* 2  verts on either side of this one */
00057     MEdge *e[2]; /* edges on either side, a bit of a waste since each edge ref's 2 edges */
00058     char flag;
00059 } ScrewVertConnect;
00060 
00061 typedef struct ScrewVertIter {
00062     ScrewVertConnect * v_array;
00063     ScrewVertConnect * v_poin;
00064     int v;
00065     int v_other;
00066     MEdge *e;
00067 } ScrewVertIter;
00068 
00069 
00070 static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, int v_init, int dir)
00071 {
00072     iter->v_array = array;
00073     iter->v = v_init;
00074 
00075     if (v_init >= 0) {
00076         iter->v_poin = &array[v_init];
00077         iter->v_other = iter->v_poin->v[dir];
00078         iter->e = iter->v_poin->e[!dir];
00079     }
00080     else {
00081         iter->v_poin= NULL;
00082         iter->e= NULL;
00083     }
00084 }   
00085 
00086 
00087 static void screwvert_iter_step(ScrewVertIter *iter)
00088 {
00089     if (iter->v_poin->v[0] == iter->v_other) {
00090         iter->v_other= iter->v;
00091         iter->v= iter->v_poin->v[1];
00092     }
00093     else if (iter->v_poin->v[1] == iter->v_other) {
00094         iter->v_other= iter->v;
00095         iter->v= iter->v_poin->v[0];
00096     }
00097     if (iter->v >= 0)   {
00098         iter->v_poin= &iter->v_array[iter->v];
00099         iter->e= iter->v_poin->e[(iter->v_poin->e[0] == iter->e)];
00100     }
00101     else {
00102         iter->e= NULL;
00103         iter->v_poin= NULL;
00104     }
00105 }
00106 
00107 
00108 static void initData(ModifierData *md)
00109 {
00110     ScrewModifierData *ltmd= (ScrewModifierData*) md;
00111     ltmd->ob_axis= NULL;
00112     ltmd->angle= M_PI * 2.0;
00113     ltmd->axis= 2;
00114     ltmd->flag= 0;
00115     ltmd->steps= 16;
00116     ltmd->render_steps= 16;
00117     ltmd->iter= 1;
00118 }
00119 
00120 static void copyData(ModifierData *md, ModifierData *target)
00121 {
00122     ScrewModifierData *sltmd= (ScrewModifierData*) md;
00123     ScrewModifierData *tltmd= (ScrewModifierData*) target;
00124     
00125     tltmd->ob_axis= sltmd->ob_axis;
00126     tltmd->angle= sltmd->angle;
00127     tltmd->axis= sltmd->axis;
00128     tltmd->flag= sltmd->flag;
00129     tltmd->steps= sltmd->steps;
00130     tltmd->render_steps= sltmd->render_steps;
00131     tltmd->screw_ofs= sltmd->screw_ofs;
00132     tltmd->iter= sltmd->iter;
00133 }
00134 
00135 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
00136                         DerivedMesh *derivedData,
00137                         int useRenderParams,
00138                         int UNUSED(isFinalCalc))
00139 {
00140     DerivedMesh *dm= derivedData;
00141     DerivedMesh *result;
00142     ScrewModifierData *ltmd= (ScrewModifierData*) md;
00143     
00144     int *origindex;
00145     int mface_index=0;
00146     int step;
00147     int i, j;
00148     unsigned int i1, i2;
00149     int step_tot= useRenderParams ? ltmd->render_steps : ltmd->steps;
00150     const int do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;
00151     int maxVerts=0, maxEdges=0, maxFaces=0;
00152     const unsigned int totvert= dm->getNumVerts(dm);
00153     const unsigned int totedge= dm->getNumEdges(dm);
00154 
00155     char axis_char= 'X', close;
00156     float angle= ltmd->angle;
00157     float screw_ofs= ltmd->screw_ofs;
00158     float axis_vec[3]= {0.0f, 0.0f, 0.0f};
00159     float tmp_vec1[3], tmp_vec2[3]; 
00160     float mat3[3][3];
00161     float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */
00162     float mtx_tx_inv[4][4]; /* inverted */
00163     float mtx_tmp_a[4][4];
00164     
00165     int vc_tot_linked= 0;
00166     short other_axis_1, other_axis_2;
00167     float *tmpf1, *tmpf2;
00168     
00169     MFace *mface_new, *mf_new;
00170     MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
00171     MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;
00172 
00173     ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL;
00174 
00175     /* dont do anything? */
00176     if (!totvert)
00177         return CDDM_from_template(dm, 0, 0, 0);
00178 
00179     switch(ltmd->axis) {
00180     case 0:
00181         other_axis_1=1;
00182         other_axis_2=2;
00183         break;
00184     case 1:
00185         other_axis_1=0;
00186         other_axis_2=2;
00187         break;
00188     default: /* 2, use default to quiet warnings */
00189         other_axis_1=0;
00190         other_axis_2=1;
00191         break;
00192     }
00193 
00194     axis_vec[ltmd->axis]= 1.0f;
00195 
00196     if (ltmd->ob_axis) {
00197         /* calc the matrix relative to the axis object */
00198         invert_m4_m4(mtx_tmp_a, ob->obmat);
00199         copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat);
00200         mult_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv);
00201 
00202         /* calc the axis vec */
00203         mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */
00204         normalize_v3(axis_vec);
00205 
00206         /* screw */
00207         if(ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
00208             /* find the offset along this axis relative to this objects matrix */
00209             float totlen = len_v3(mtx_tx[3]);
00210 
00211             if(totlen != 0.0f) {
00212                 float zero[3]={0.0f, 0.0f, 0.0f};
00213                 float cp[3];                
00214                 screw_ofs= closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
00215             }
00216             else {
00217                 screw_ofs= 0.0f;
00218             }
00219         }
00220 
00221         /* angle */
00222 
00223 #if 0   // cant incluide this, not predictable enough, though quite fun,.
00224         if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
00225             float mtx3_tx[3][3];
00226             copy_m3_m4(mtx3_tx, mtx_tx);
00227 
00228             float vec[3] = {0,1,0};
00229             float cross1[3];
00230             float cross2[3];
00231             cross_v3_v3v3(cross1, vec, axis_vec);
00232 
00233             mul_v3_m3v3(cross2, mtx3_tx, cross1);
00234             {
00235                 float c1[3];
00236                 float c2[3];
00237                 float axis_tmp[3];
00238 
00239                 cross_v3_v3v3(c1, cross2, axis_vec);
00240                 cross_v3_v3v3(c2, axis_vec, c1);
00241 
00242 
00243                 angle= angle_v3v3(cross1, c2);
00244 
00245                 cross_v3_v3v3(axis_tmp, cross1, c2);
00246                 normalize_v3(axis_tmp);
00247 
00248                 if(len_v3v3(axis_tmp, axis_vec) > 1.0f)
00249                     angle= -angle;
00250 
00251             }
00252         }
00253 #endif
00254     }
00255     else {
00256         /* exis char is used by i_rotate*/
00257         axis_char += ltmd->axis; /* 'X' + axis */
00258 
00259         /* useful to be able to use the axis vec in some cases still */
00260         zero_v3(axis_vec);
00261         axis_vec[ltmd->axis]= 1.0f;
00262     }
00263 
00264     /* apply the multiplier */
00265     angle *= ltmd->iter;
00266     screw_ofs *= ltmd->iter;
00267 
00268     /* multiplying the steps is a bit tricky, this works best */
00269     step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
00270 
00271     /* will the screw be closed?
00272      * Note! smaller then FLT_EPSILON*100 gives problems with float precision so its never closed. */
00273     if (fabsf(screw_ofs) <= (FLT_EPSILON*100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON*100.0f)) {
00274         close= 1;
00275         step_tot--;
00276         if(step_tot < 3) step_tot= 3;
00277     
00278         maxVerts =  totvert  * step_tot; /* -1 because we're joining back up */
00279         maxEdges =  (totvert * step_tot) + /* these are the edges between new verts */
00280                     (totedge * step_tot); /* -1 because vert edges join */
00281         maxFaces =  totedge * step_tot;
00282 
00283         screw_ofs= 0.0f;
00284     }
00285     else {
00286         close= 0;
00287         if(step_tot < 3) step_tot= 3;
00288 
00289         maxVerts =  totvert  * step_tot; /* -1 because we're joining back up */
00290         maxEdges =  (totvert * (step_tot-1)) + /* these are the edges between new verts */
00291                     (totedge * step_tot); /* -1 because vert edges join */
00292         maxFaces =  totedge * (step_tot-1);
00293     }
00294     
00295     result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces);
00296     
00297     /* copy verts from mesh */
00298     mvert_orig =    dm->getVertArray(dm);
00299     medge_orig =    dm->getEdgeArray(dm);
00300     
00301     mvert_new =     result->getVertArray(result);
00302     mface_new =     result->getFaceArray(result);
00303     medge_new =     result->getEdgeArray(result);
00304     
00305     origindex= result->getFaceDataArray(result, CD_ORIGINDEX);
00306 
00307     DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */
00308     
00309     /* Set the locations of the first set of verts */
00310     
00311     mv_new= mvert_new;
00312     mv_orig= mvert_orig;
00313     
00314     /* Copy the first set of edges */
00315     med_orig= medge_orig;
00316     med_new= medge_new;
00317     for (i=0; i < totedge; i++, med_orig++, med_new++) {
00318         med_new->v1= med_orig->v1;
00319         med_new->v2= med_orig->v2;
00320         med_new->crease= med_orig->crease;
00321         med_new->flag= med_orig->flag &  ~ME_LOOSEEDGE;
00322     }
00323     
00324     if(ltmd->flag & MOD_SCREW_NORMAL_CALC) {
00325         /*
00326          * Normal Calculation (for face flipping)
00327          * Sort edge verts for correct face flipping
00328          * NOT REALLY NEEDED but face flipping is nice.
00329          *
00330          * */
00331 
00332 
00333         /* Notice!
00334          *
00335          * Since we are only ordering the edges here it can avoid mallocing the
00336          * extra space by abusing the vert array berfore its filled with new verts.
00337          * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert
00338          * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3
00339          * so its safe to use the second 2 thrids of MVert the array for vert_connect,
00340          * just make sure ScrewVertConnect struct is no more then twice as big as MVert,
00341          * at the moment there is no chance of that being a problem,
00342          * unless MVert becomes half its current size.
00343          *
00344          * once the edges are ordered, vert_connect is not needed and it can be used for verts
00345          *
00346          * This makes the modifier faster with one less alloc.
00347          */
00348 
00349         vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect");
00350         //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */
00351         vc= vert_connect;
00352 
00353         /* Copy Vert Locations */
00354         /* - We can do this in a later loop - only do here if no normal calc */
00355         if (!totedge) {
00356             for (i=0; i < totvert; i++, mv_orig++, mv_new++) {
00357                 copy_v3_v3(mv_new->co, mv_orig->co);
00358                 normalize_v3_v3(vc->no, mv_new->co); /* no edges- this is really a dummy normal */
00359             }
00360         }
00361         else {
00362             /*printf("\n\n\n\n\nStarting Modifier\n");*/
00363             /* set edge users */
00364             med_new= medge_new;
00365             mv_new= mvert_new;
00366 
00367             if (ltmd->ob_axis) {
00368                 /*mtx_tx is initialized early on */
00369                 for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
00370                     vc->co[0]= mv_new->co[0]= mv_orig->co[0];
00371                     vc->co[1]= mv_new->co[1]= mv_orig->co[1];
00372                     vc->co[2]= mv_new->co[2]= mv_orig->co[2];
00373 
00374                     vc->flag= 0;
00375                     vc->e[0]= vc->e[1]= NULL;
00376                     vc->v[0]= vc->v[1]= -1;
00377 
00378                     mul_m4_v3(mtx_tx, vc->co);
00379                     /* length in 2d, dont sqrt because this is only for comparison */
00380                     vc->dist =  vc->co[other_axis_1]*vc->co[other_axis_1] +
00381                                 vc->co[other_axis_2]*vc->co[other_axis_2];
00382 
00383                     /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
00384                 }
00385             }
00386             else {
00387                 for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
00388                     vc->co[0]= mv_new->co[0]= mv_orig->co[0];
00389                     vc->co[1]= mv_new->co[1]= mv_orig->co[1];
00390                     vc->co[2]= mv_new->co[2]= mv_orig->co[2];
00391 
00392                     vc->flag= 0;
00393                     vc->e[0]= vc->e[1]= NULL;
00394                     vc->v[0]= vc->v[1]= -1;
00395 
00396                     /* length in 2d, dont sqrt because this is only for comparison */
00397                     vc->dist =  vc->co[other_axis_1]*vc->co[other_axis_1] +
00398                                 vc->co[other_axis_2]*vc->co[other_axis_2];
00399 
00400                     /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
00401                 }
00402             }
00403 
00404             /* this loop builds connectivity info for verts */
00405             for (i=0; i<totedge; i++, med_new++) {
00406                 vc= &vert_connect[med_new->v1];
00407 
00408                 if (vc->v[0] == -1) { /* unused */
00409                     vc->v[0]= med_new->v2;
00410                     vc->e[0]= med_new;
00411                 }
00412                 else if (vc->v[1] == -1) {
00413                     vc->v[1]= med_new->v2;
00414                     vc->e[1]= med_new;
00415                 }
00416                 else {
00417                     vc->v[0]= vc->v[1]= -2; /* erro value  - dont use, 3 edges on vert */
00418                 }
00419 
00420                 vc= &vert_connect[med_new->v2];
00421 
00422                 /* same as above but swap v1/2 */
00423                 if (vc->v[0] == -1) { /* unused */
00424                     vc->v[0]= med_new->v1;
00425                     vc->e[0]= med_new;
00426                 }
00427                 else if (vc->v[1] == -1) {
00428                     vc->v[1]= med_new->v1;
00429                     vc->e[1]= med_new;
00430                 }
00431                 else {
00432                     vc->v[0]= vc->v[1]= -2; /* erro value  - dont use, 3 edges on vert */
00433                 }
00434             }
00435 
00436             /* find the first vert */
00437             vc= vert_connect;
00438             for (i=0; i < totvert; i++, vc++) {
00439                 /* Now do search for connected verts, order all edges and flip them
00440                  * so resulting faces are flipped the right way */
00441                 vc_tot_linked= 0; /* count the number of linked verts for this loop */
00442                 if (vc->flag == 0) {
00443                     int v_best=-1, ed_loop_closed=0; /* vert and vert new */
00444                     ScrewVertIter lt_iter;
00445                     int ed_loop_flip= 0; /* compiler complains if not initialized, but it should be initialized below */
00446                     float fl= -1.0f;
00447 
00448                     /*printf("Loop on connected vert: %i\n", i);*/
00449 
00450                     for(j=0; j<2; j++) {
00451                         /*printf("\tSide: %i\n", j);*/
00452                         screwvert_iter_init(&lt_iter, vert_connect, i, j);
00453                         if (j == 1) {
00454                             screwvert_iter_step(&lt_iter);
00455                         }
00456                         while (lt_iter.v_poin) {
00457                             /*printf("\t\tVERT: %i\n", lt_iter.v);*/
00458                             if (lt_iter.v_poin->flag) {
00459                                 /*printf("\t\t\tBreaking Found end\n");*/
00460                                 //endpoints[0]= endpoints[1]= -1;
00461                                 ed_loop_closed= 1; /* circle */
00462                                 break;
00463                             }
00464                             lt_iter.v_poin->flag= 1;
00465                             vc_tot_linked++;
00466                             /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/
00467                             if (fl <= lt_iter.v_poin->dist) {
00468                                 fl= lt_iter.v_poin->dist;
00469                                 v_best= lt_iter.v;
00470                                 /*printf("\t\t\tVERT BEST: %i\n", v_best);*/
00471                             }
00472                             screwvert_iter_step(&lt_iter);
00473                             if (!lt_iter.v_poin) {
00474                                 /*printf("\t\t\tFound End Also Num %i\n", j);*/
00475                                 /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */
00476                                 break;
00477                             }
00478                         }
00479                     }
00480 
00481                     /* now we have a collection of used edges. flip their edges the right way*/
00482                     /*if (v_best != -1) - */
00483 
00484                     /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/
00485 
00486                     if (vc_tot_linked>1) {
00487                         float vf_1, vf_2, vf_best;
00488 
00489                         vc_tmp= &vert_connect[v_best];
00490 
00491                         tmpf1= vert_connect[vc_tmp->v[0]].co;
00492                         tmpf2= vert_connect[vc_tmp->v[1]].co;
00493 
00494 
00495                         /* edge connects on each side! */
00496                         if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) {
00497                             /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
00498                             /* find out which is higher */
00499 
00500                             vf_1= tmpf1[ltmd->axis];
00501                             vf_2= tmpf2[ltmd->axis];
00502                             vf_best= vc_tmp->co[ltmd->axis];
00503 
00504                             if (vf_1 < vf_best && vf_best < vf_2) {
00505                                 ed_loop_flip= 0;
00506                             }
00507                             else if (vf_1 > vf_best && vf_best > vf_2) {
00508                                 ed_loop_flip= 1;
00509                             }
00510                             else {
00511                                 /* not so simple to work out which edge is higher */
00512                                 sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co);
00513                                 sub_v3_v3v3(tmp_vec2, tmpf2, vc_tmp->co);
00514                                 normalize_v3(tmp_vec1);
00515                                 normalize_v3(tmp_vec2);
00516 
00517                                 if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) {
00518                                     ed_loop_flip= 1;
00519                                 }
00520                                 else {
00521                                     ed_loop_flip= 0;
00522                                 }
00523                             }
00524                         }
00525                         else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */
00526                             /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
00527                             if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
00528                                 ed_loop_flip= 1;
00529                             }
00530                             else { /* best is below or even... in even case we cant know whet  to do. */
00531                                 ed_loop_flip= 0;
00532                             }
00533 
00534                         }/* else {
00535                             printf("No Connected ___\n");
00536                         }*/
00537 
00538                         /*printf("flip direction %i\n", ed_loop_flip);*/
00539 
00540 
00541                         /* switch the flip option if set
00542                          * note: flip is now done at face level so copying vgroup slizes is easier */
00543                         /*                      
00544                         if (do_flip)
00545                             ed_loop_flip= !ed_loop_flip;
00546                         */
00547 
00548                         if (angle < 0.0f)
00549                             ed_loop_flip= !ed_loop_flip;
00550 
00551                         /* if its closed, we only need 1 loop */
00552                         for(j=ed_loop_closed; j<2; j++) {
00553                             /*printf("Ordering Side J %i\n", j);*/
00554 
00555                             screwvert_iter_init(&lt_iter, vert_connect, v_best, j);
00556                             /*printf("\n\nStarting - Loop\n");*/
00557                             lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */
00558 
00559 
00560                             /* If this is the vert off the best vert and
00561                              * the best vert has 2 edges connected too it
00562                              * then swap the flip direction */
00563                             if (j == 1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1))
00564                                 ed_loop_flip= !ed_loop_flip;
00565 
00566                             while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
00567                                 /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/
00568 
00569                                 lt_iter.v_poin->flag= 2;
00570                                 if (lt_iter.e) {
00571                                     if (lt_iter.v == lt_iter.e->v1) {
00572                                         if (ed_loop_flip == 0) {
00573                                             /*printf("\t\t\tFlipping 0\n");*/
00574                                             SWAP(unsigned int, lt_iter.e->v1, lt_iter.e->v2);
00575                                         }/* else {
00576                                             printf("\t\t\tFlipping Not 0\n");
00577                                         }*/
00578                                     }
00579                                     else if (lt_iter.v == lt_iter.e->v2) {
00580                                         if (ed_loop_flip == 1) {
00581                                             /*printf("\t\t\tFlipping 1\n");*/
00582                                             SWAP(unsigned int, lt_iter.e->v1, lt_iter.e->v2);
00583                                         }/* else {
00584                                             printf("\t\t\tFlipping Not 1\n");
00585                                         }*/
00586                                     }/* else {
00587                                         printf("\t\tIncorrect edge topology");
00588                                     }*/
00589                                 }/* else {
00590                                     printf("\t\tNo Edge at this point\n");
00591                                 }*/
00592                                 screwvert_iter_step(&lt_iter);
00593                             }
00594                         }
00595                     }
00596                 }
00597 
00598                 /* *VERTEX NORMALS*
00599                  * we know the surrounding edges are ordered correctly now
00600                  * so its safe to create vertex normals.
00601                  *
00602                  * calculate vertex normals that can be propodated on lathing
00603                  * use edge connectivity work this out */
00604                 if (vc->v[0] >= 0) {
00605                     if (vc->v[1] >= 0) {
00606                         /* 2 edges connedted */
00607                         /* make 2 connecting vert locations relative to the middle vert */
00608                         sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
00609                         sub_v3_v3v3(tmp_vec2, mvert_new[vc->v[1]].co, mvert_new[i].co);
00610                         /* normalize so both edges have the same influence, no matter their length */
00611                         normalize_v3(tmp_vec1);
00612                         normalize_v3(tmp_vec2);
00613 
00614                         /* vc_no_tmp1 - this line is the average direction of both connecting edges
00615                          *
00616                          * Use the edge order to make the subtraction, flip the normal the right way
00617                          * edge should be there but check just in case... */
00618                         if (vc->e && vc->e[0]->v1 == i) {
00619                             sub_v3_v3(tmp_vec1, tmp_vec2);
00620                         }
00621                         else {
00622                             sub_v3_v3v3(tmp_vec1, tmp_vec2, tmp_vec1);
00623                         }
00624                     }
00625                     else {
00626                         /* only 1 edge connected - same as above except
00627                          * dont need to average edge direction */
00628                         if (vc->e && vc->e[0]->v2 == i) {
00629                             sub_v3_v3v3(tmp_vec1, mvert_new[i].co, mvert_new[vc->v[0]].co);
00630                         }
00631                         else {
00632                             sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
00633                         }
00634                     }
00635 
00636                     /* vc_no_tmp2 - is a line 90d from the pivot to the vec
00637                      * This is used so the resulting normal points directly away from the middle */
00638                     cross_v3_v3v3(tmp_vec2, axis_vec, vc->co);
00639 
00640                     /* edge average vector and right angle to the pivot make the normal */
00641                     cross_v3_v3v3(vc->no, tmp_vec1, tmp_vec2);
00642 
00643                 }
00644                 else {
00645                     copy_v3_v3(vc->no, vc->co);
00646                 }
00647 
00648                 /* we wont be looping on this data again so copy normals here */
00649                 if (angle < 0.0f)
00650                     negate_v3(vc->no);
00651 
00652                 normalize_v3(vc->no);
00653                 normal_float_to_short_v3(mvert_new[i].no, vc->no);
00654 
00655                 /* Done with normals */
00656             }
00657         }
00658     }
00659     else {
00660         mv_orig= mvert_orig;
00661         mv_new= mvert_new;
00662 
00663         for (i=0; i < totvert; i++, mv_new++, mv_orig++) {
00664             copy_v3_v3(mv_new->co, mv_orig->co);
00665         }
00666     }
00667     /* done with edge connectivity based normal flipping */
00668     
00669     /* Add Faces */
00670     for (step=1; step < step_tot; step++) {
00671         const int varray_stride= totvert * step;
00672         float step_angle;
00673         float nor_tx[3];
00674         float mat[4][4];
00675         /* Rotation Matrix */
00676         step_angle= (angle / (step_tot - (!close))) * step;
00677 
00678         if (ltmd->ob_axis) {
00679             axis_angle_to_mat3(mat3, axis_vec, step_angle);
00680             copy_m4_m3(mat, mat3);
00681         }
00682         else {
00683             unit_m4(mat);
00684             rotate_m4(mat, axis_char, step_angle);
00685             copy_m3_m4(mat3, mat);
00686         }
00687 
00688         if(screw_ofs)
00689             madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)step / (float)(step_tot-1)));
00690 
00691         /* copy a slice */
00692         DM_copy_vert_data(dm, result, 0, varray_stride, totvert);
00693         
00694         mv_new_base= mvert_new;
00695         mv_new= &mvert_new[varray_stride]; /* advance to the next slice */
00696         
00697         for (j=0; j<totvert; j++, mv_new_base++, mv_new++) {
00698             /* set normal */
00699             if(vert_connect) {
00700                 mul_v3_m3v3(nor_tx, mat3, vert_connect[j].no);
00701 
00702                 /* set the normal now its transformed */
00703                 normal_float_to_short_v3(mv_new->no, nor_tx);
00704             }
00705             
00706             /* set location */
00707             copy_v3_v3(mv_new->co, mv_new_base->co);
00708             
00709             /* only need to set these if using non cleared memory */
00710             /*mv_new->mat_nr= mv_new->flag= 0;*/
00711                 
00712             if (ltmd->ob_axis) {
00713                 sub_v3_v3(mv_new->co, mtx_tx[3]);
00714 
00715                 mul_m4_v3(mat, mv_new->co);
00716 
00717                 add_v3_v3(mv_new->co, mtx_tx[3]);
00718             }
00719             else {
00720                 mul_m4_v3(mat, mv_new->co);
00721             }
00722             
00723             /* add the new edge */
00724             med_new->v1= varray_stride + j;
00725             med_new->v2= med_new->v1 - totvert;
00726             med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
00727             med_new++;
00728         }
00729     }
00730 
00731     /* we can avoid if using vert alloc trick */
00732     if(vert_connect) {
00733         MEM_freeN(vert_connect);
00734         vert_connect= NULL;
00735     }
00736 
00737     if (close) {
00738         /* last loop of edges, previous loop dosnt account for the last set of edges */
00739         const int varray_stride= (step_tot - 1) * totvert;
00740 
00741         for (i=0; i<totvert; i++) {
00742             med_new->v1= i;
00743             med_new->v2= varray_stride + i;
00744             med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
00745             med_new++;
00746         }
00747     }
00748     
00749     mf_new= mface_new;
00750     med_new_firstloop= medge_new;
00751     
00752     for (i=0; i < totedge; i++, med_new_firstloop++) {
00753         /* for each edge, make a cylinder of quads */
00754         i1= med_new_firstloop->v1;
00755         i2= med_new_firstloop->v2;
00756 
00757         for (step=0; step < step_tot-1; step++) {
00758             
00759             /* new face */
00760             if(do_flip) {
00761                 mf_new->v4= i1;
00762                 mf_new->v3= i2;
00763                 mf_new->v2= i2 + totvert;
00764                 mf_new->v1= i1 + totvert;
00765             }
00766             else {
00767                 mf_new->v1= i1;
00768                 mf_new->v2= i2;
00769                 mf_new->v3= i2 + totvert;
00770                 mf_new->v4= i1 + totvert;
00771             }
00772             
00773             if( !mf_new->v3 || !mf_new->v4 ) {
00774                 SWAP(unsigned int, mf_new->v1, mf_new->v3);
00775                 SWAP(unsigned int, mf_new->v2, mf_new->v4);
00776             }
00777             mf_new->flag= ME_SMOOTH;
00778             origindex[mface_index]= ORIGINDEX_NONE;
00779             mf_new++;
00780             mface_index++;
00781             
00782             /* new vertical edge */
00783             if (step) { /* The first set is already dome */
00784                 med_new->v1= i1;
00785                 med_new->v2= i2;
00786                 med_new->flag= med_new_firstloop->flag;
00787                 med_new->crease= med_new_firstloop->crease;
00788                 med_new++;
00789             }
00790             i1 += totvert;
00791             i2 += totvert;
00792         }
00793         
00794         /* close the loop*/
00795         if (close) { 
00796             if(do_flip) {
00797                 mf_new->v4= i1;
00798                 mf_new->v3= i2;
00799                 mf_new->v2= med_new_firstloop->v2;
00800                 mf_new->v1= med_new_firstloop->v1;
00801             }
00802             else {
00803                 mf_new->v1= i1;
00804                 mf_new->v2= i2;
00805                 mf_new->v3= med_new_firstloop->v2;
00806                 mf_new->v4= med_new_firstloop->v1;
00807             }
00808 
00809             if( !mf_new->v3 || !mf_new->v4 ) {
00810                 SWAP(unsigned int, mf_new->v1, mf_new->v3);
00811                 SWAP(unsigned int, mf_new->v2, mf_new->v4);
00812             }
00813             mf_new->flag= ME_SMOOTH;
00814             origindex[mface_index]= ORIGINDEX_NONE;
00815             mf_new++;
00816             mface_index++;
00817         }
00818         
00819         /* new vertical edge */
00820         med_new->v1= i1;
00821         med_new->v2= i2;
00822         med_new->flag= med_new_firstloop->flag & ~ME_LOOSEEDGE;
00823         med_new->crease= med_new_firstloop->crease;
00824         med_new++;
00825     }
00826     
00827     if((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) {
00828         CDDM_calc_normals(result);
00829     }
00830 
00831     return result;
00832 }
00833 
00834 
00835 static void updateDepgraph(ModifierData *md, DagForest *forest,
00836                         struct Scene *UNUSED(scene),
00837                         Object *UNUSED(ob),
00838                         DagNode *obNode)
00839 {
00840     ScrewModifierData *ltmd= (ScrewModifierData*) md;
00841 
00842     if(ltmd->ob_axis) {
00843         DagNode *curNode= dag_get_node(forest, ltmd->ob_axis);
00844 
00845         dag_add_relation(forest, curNode, obNode,
00846                          DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
00847                          "Screw Modifier");
00848     }
00849 }
00850 
00851 static void foreachObjectLink(
00852                 ModifierData *md, Object *ob,
00853                 void (*walk)(void *userData, Object *ob, Object **obpoin),
00854                 void *userData)
00855 {
00856     ScrewModifierData *ltmd= (ScrewModifierData*) md;
00857 
00858     walk(userData, ob, &ltmd->ob_axis);
00859 }
00860 
00861 /* This dosnt work with material*/
00862 static DerivedMesh *applyModifierEM(
00863                         ModifierData *md,
00864                         Object *ob,
00865                         struct EditMesh *UNUSED(editData),
00866                         DerivedMesh *derivedData)
00867 {
00868     return applyModifier(md, ob, derivedData, 0, 1);
00869 }
00870 
00871 static int dependsOnTime(ModifierData *UNUSED(md))
00872 {
00873     return 0;
00874 }
00875 
00876 
00877 ModifierTypeInfo modifierType_Screw = {
00878     /* name */              "Screw",
00879     /* structName */        "ScrewModifierData",
00880     /* structSize */        sizeof(ScrewModifierData),
00881     /* type */              eModifierTypeType_Constructive,
00882 
00883     /* flags */             eModifierTypeFlag_AcceptsMesh
00884                             | eModifierTypeFlag_AcceptsCVs
00885                             | eModifierTypeFlag_SupportsEditmode
00886                             | eModifierTypeFlag_EnableInEditmode,
00887 
00888     /* copyData */          copyData,
00889     /* deformVerts */       NULL,
00890     /* deformMatrices */    NULL,
00891     /* deformVertsEM */     NULL,
00892     /* deformMatricesEM */  NULL,
00893     /* applyModifier */     applyModifier,
00894     /* applyModifierEM */   applyModifierEM,
00895     /* initData */          initData,
00896     /* requiredDataMask */  NULL,
00897     /* freeData */          NULL,
00898     /* isDisabled */        NULL,
00899     /* updateDepgraph */    updateDepgraph,
00900     /* dependsOnTime */     dependsOnTime,
00901     /* dependsOnNormals */  NULL,
00902     /* foreachObjectLink */ foreachObjectLink,
00903     /* foreachIDLink */     NULL,
00904     /* foreachTexLink */    NULL,
00905 };