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