Spelling Cleanup
[blender.git] / source / blender / modifiers / intern / MOD_screw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software  Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Dunbar
22  *                 Ton Roosendaal,
23  *                 Ben Batt,
24  *                 Brecht Van Lommel,
25  *                 Campbell Barton
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  */
30
31 /** \file blender/modifiers/intern/MOD_screw.c
32  *  \ingroup modifiers
33  */
34
35
36 /* Screw modifier: revolves the edges about an axis */
37
38 #include "DNA_meshdata_types.h"
39 #include "DNA_object_types.h"
40
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43
44
45 #include "BKE_cdderivedmesh.h"
46
47 #include "depsgraph_private.h"
48 #include "MOD_modifiertypes.h"
49 #include "MEM_guardedalloc.h"
50
51 /* used for gathering edge connectivity */
52 typedef struct ScrewVertConnect {
53         float dist;  /* distance from the center axis */
54         float co[3]; /* loaction relative to the transformed axis */
55         float no[3]; /* calc normal of the vertex */
56         int v[2]; /* 2  verts on either side of this one */
57         MEdge *e[2]; /* edges on either side, a bit of a waste since each edge ref's 2 edges */
58         char flag;
59 } ScrewVertConnect;
60
61 typedef struct ScrewVertIter {
62         ScrewVertConnect * v_array;
63         ScrewVertConnect * v_poin;
64         int v;
65         int v_other;
66         MEdge *e;
67 } ScrewVertIter;
68
69
70 static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, int v_init, int dir)
71 {
72         iter->v_array = array;
73         iter->v = v_init;
74
75         if (v_init >= 0) {
76                 iter->v_poin = &array[v_init];
77                 iter->v_other = iter->v_poin->v[dir];
78                 iter->e = iter->v_poin->e[!dir];
79         }
80         else {
81                 iter->v_poin= NULL;
82                 iter->e= NULL;
83         }
84 }       
85
86
87 static void screwvert_iter_step(ScrewVertIter *iter)
88 {
89         if (iter->v_poin->v[0] == iter->v_other) {
90                 iter->v_other= iter->v;
91                 iter->v= iter->v_poin->v[1];
92         }
93         else if (iter->v_poin->v[1] == iter->v_other) {
94                 iter->v_other= iter->v;
95                 iter->v= iter->v_poin->v[0];
96         }
97         if (iter->v >= 0)       {
98                 iter->v_poin= &iter->v_array[iter->v];
99                 iter->e= iter->v_poin->e[(iter->v_poin->e[0] == iter->e)];
100         }
101         else {
102                 iter->e= NULL;
103                 iter->v_poin= NULL;
104         }
105 }
106
107
108 static void initData(ModifierData *md)
109 {
110         ScrewModifierData *ltmd= (ScrewModifierData*) md;
111         ltmd->ob_axis= NULL;
112         ltmd->angle= M_PI * 2.0;
113         ltmd->axis= 2;
114         ltmd->flag= 0;
115         ltmd->steps= 16;
116         ltmd->render_steps= 16;
117         ltmd->iter= 1;
118 }
119
120 static void copyData(ModifierData *md, ModifierData *target)
121 {
122         ScrewModifierData *sltmd= (ScrewModifierData*) md;
123         ScrewModifierData *tltmd= (ScrewModifierData*) target;
124         
125         tltmd->ob_axis= sltmd->ob_axis;
126         tltmd->angle= sltmd->angle;
127         tltmd->axis= sltmd->axis;
128         tltmd->flag= sltmd->flag;
129         tltmd->steps= sltmd->steps;
130         tltmd->render_steps= sltmd->render_steps;
131         tltmd->screw_ofs= sltmd->screw_ofs;
132         tltmd->iter= sltmd->iter;
133 }
134
135 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
136                                                 DerivedMesh *derivedData,
137                                                 int useRenderParams,
138                                                 int UNUSED(isFinalCalc))
139 {
140         DerivedMesh *dm= derivedData;
141         DerivedMesh *result;
142         ScrewModifierData *ltmd= (ScrewModifierData*) md;
143         
144         int *origindex;
145         int mpoly_index=0;
146         int step;
147         int i, j;
148         unsigned int i1, i2;
149         int step_tot= useRenderParams ? ltmd->render_steps : ltmd->steps;
150         const int do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;
151         int maxVerts=0, maxEdges=0, maxPolys=0;
152         const unsigned int totvert= dm->getNumVerts(dm);
153         const unsigned int totedge= dm->getNumEdges(dm);
154
155         char axis_char= 'X', close;
156         float angle= ltmd->angle;
157         float screw_ofs= ltmd->screw_ofs;
158         float axis_vec[3]= {0.0f, 0.0f, 0.0f};
159         float tmp_vec1[3], tmp_vec2[3]; 
160         float mat3[3][3];
161         float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */
162         float mtx_tx_inv[4][4]; /* inverted */
163         float mtx_tmp_a[4][4];
164         
165         int vc_tot_linked= 0;
166         short other_axis_1, other_axis_2;
167         float *tmpf1, *tmpf2;
168
169         int edge_offset;
170         
171         MPoly *mpoly_new, *mp_new;
172         MLoop *mloop_new, *ml_new;
173         MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
174         MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;
175
176         ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL;
177
178         /* dont do anything? */
179         if (!totvert)
180                 return CDDM_from_template(dm, 0, 0, 0, 0, 0);
181
182         switch(ltmd->axis) {
183         case 0:
184                 other_axis_1=1;
185                 other_axis_2=2;
186                 break;
187         case 1:
188                 other_axis_1=0;
189                 other_axis_2=2;
190                 break;
191         default: /* 2, use default to quiet warnings */
192                 other_axis_1=0;
193                 other_axis_2=1;
194                 break;
195         }
196
197         axis_vec[ltmd->axis]= 1.0f;
198
199         if (ltmd->ob_axis) {
200                 /* calc the matrix relative to the axis object */
201                 invert_m4_m4(mtx_tmp_a, ob->obmat);
202                 copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat);
203                 mult_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv);
204
205                 /* calc the axis vec */
206                 mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */
207                 normalize_v3(axis_vec);
208
209                 /* screw */
210                 if(ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
211                         /* find the offset along this axis relative to this objects matrix */
212                         float totlen = len_v3(mtx_tx[3]);
213
214                         if(totlen != 0.0f) {
215                                 float zero[3]={0.0f, 0.0f, 0.0f};
216                                 float cp[3];                            
217                                 screw_ofs= closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
218                         }
219                         else {
220                                 screw_ofs= 0.0f;
221                         }
222                 }
223
224                 /* angle */
225
226 #if 0   // cant incluide this, not predictable enough, though quite fun,.
227                 if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
228                         float mtx3_tx[3][3];
229                         copy_m3_m4(mtx3_tx, mtx_tx);
230
231                         float vec[3] = {0,1,0};
232                         float cross1[3];
233                         float cross2[3];
234                         cross_v3_v3v3(cross1, vec, axis_vec);
235
236                         mul_v3_m3v3(cross2, mtx3_tx, cross1);
237                         {
238                                 float c1[3];
239                                 float c2[3];
240                                 float axis_tmp[3];
241
242                                 cross_v3_v3v3(c1, cross2, axis_vec);
243                                 cross_v3_v3v3(c2, axis_vec, c1);
244
245
246                                 angle= angle_v3v3(cross1, c2);
247
248                                 cross_v3_v3v3(axis_tmp, cross1, c2);
249                                 normalize_v3(axis_tmp);
250
251                                 if(len_v3v3(axis_tmp, axis_vec) > 1.0f)
252                                         angle= -angle;
253
254                         }
255                 }
256 #endif
257         }
258         else {
259                 /* exis char is used by i_rotate*/
260                 axis_char += ltmd->axis; /* 'X' + axis */
261
262                 /* useful to be able to use the axis vec in some cases still */
263                 zero_v3(axis_vec);
264                 axis_vec[ltmd->axis]= 1.0f;
265         }
266
267         /* apply the multiplier */
268         angle *= ltmd->iter;
269         screw_ofs *= ltmd->iter;
270
271         /* multiplying the steps is a bit tricky, this works best */
272         step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
273
274         /* will the screw be closed?
275          * Note! smaller then FLT_EPSILON*100 gives problems with float precision so its never closed. */
276         if (fabsf(screw_ofs) <= (FLT_EPSILON*100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON*100.0f)) {
277                 close= 1;
278                 step_tot--;
279                 if(step_tot < 3) step_tot= 3;
280         
281                 maxVerts =      totvert  * step_tot; /* -1 because we're joining back up */
282                 maxEdges =      (totvert * step_tot) + /* these are the edges between new verts */
283                                         (totedge * step_tot); /* -1 because vert edges join */
284                 maxPolys =      totedge * step_tot;
285
286                 screw_ofs= 0.0f;
287         }
288         else {
289                 close= 0;
290                 if(step_tot < 3) step_tot= 3;
291
292                 maxVerts =      totvert  * step_tot; /* -1 because we're joining back up */
293                 maxEdges =      (totvert * (step_tot-1)) + /* these are the edges between new verts */
294                                         (totedge * step_tot); /* -1 because vert edges join */
295                 maxPolys =      totedge * (step_tot-1);
296         }
297         
298         result= CDDM_from_template(dm, maxVerts, maxEdges, 0, maxPolys * 4, maxPolys);
299         
300         /* copy verts from mesh */
301         mvert_orig =    dm->getVertArray(dm);
302         medge_orig =    dm->getEdgeArray(dm);
303         
304         mvert_new =             result->getVertArray(result);
305         mpoly_new =             result->getPolyArray(result);
306         mloop_new =             result->getLoopArray(result);
307         medge_new =             result->getEdgeArray(result);
308
309         if (!CustomData_has_layer(&result->polyData, CD_ORIGINDEX)) {
310                 CustomData_add_layer(&result->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, maxPolys);
311         }
312
313 #if 0 // trunk
314         origindex = result->getPolyDataArray(result, CD_ORIGINDEX);
315 #else // bmesh
316         origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
317 #endif
318
319         DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */
320         
321         /* Set the locations of the first set of verts */
322         
323         mv_new= mvert_new;
324         mv_orig= mvert_orig;
325         
326         /* Copy the first set of edges */
327         med_orig= medge_orig;
328         med_new= medge_new;
329         for (i=0; i < totedge; i++, med_orig++, med_new++) {
330                 med_new->v1= med_orig->v1;
331                 med_new->v2= med_orig->v2;
332                 med_new->crease= med_orig->crease;
333                 med_new->flag= med_orig->flag &  ~ME_LOOSEEDGE;
334         }
335         
336         if(ltmd->flag & MOD_SCREW_NORMAL_CALC) {
337                 /*
338                  * Normal Calculation (for face flipping)
339                  * Sort edge verts for correct face flipping
340                  * NOT REALLY NEEDED but face flipping is nice.
341                  *
342                  * */
343
344
345                 /* Notice!
346                  *
347                  * Since we are only ordering the edges here it can avoid mallocing the
348                  * extra space by abusing the vert array berfore its filled with new verts.
349                  * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert
350                  * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3
351                  * so its safe to use the second 2 thrids of MVert the array for vert_connect,
352                  * just make sure ScrewVertConnect struct is no more then twice as big as MVert,
353                  * at the moment there is no chance of that being a problem,
354                  * unless MVert becomes half its current size.
355                  *
356                  * once the edges are ordered, vert_connect is not needed and it can be used for verts
357                  *
358                  * This makes the modifier faster with one less alloc.
359                  */
360
361                 vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect");
362                 //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */
363                 vc= vert_connect;
364
365                 /* Copy Vert Locations */
366                 /* - We can do this in a later loop - only do here if no normal calc */
367                 if (!totedge) {
368                         for (i=0; i < totvert; i++, mv_orig++, mv_new++) {
369                                 copy_v3_v3(mv_new->co, mv_orig->co);
370                                 normalize_v3_v3(vc->no, mv_new->co); /* no edges- this is really a dummy normal */
371                         }
372                 }
373                 else {
374                         /*printf("\n\n\n\n\nStarting Modifier\n");*/
375                         /* set edge users */
376                         med_new= medge_new;
377                         mv_new= mvert_new;
378
379                         if (ltmd->ob_axis) {
380                                 /*mtx_tx is initialized early on */
381                                 for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
382                                         vc->co[0]= mv_new->co[0]= mv_orig->co[0];
383                                         vc->co[1]= mv_new->co[1]= mv_orig->co[1];
384                                         vc->co[2]= mv_new->co[2]= mv_orig->co[2];
385
386                                         vc->flag= 0;
387                                         vc->e[0]= vc->e[1]= NULL;
388                                         vc->v[0]= vc->v[1]= -1;
389
390                                         mul_m4_v3(mtx_tx, vc->co);
391                                         /* length in 2d, dont sqrt because this is only for comparison */
392                                         vc->dist =      vc->co[other_axis_1]*vc->co[other_axis_1] +
393                                                                 vc->co[other_axis_2]*vc->co[other_axis_2];
394
395                                         /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
396                                 }
397                         }
398                         else {
399                                 for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
400                                         vc->co[0]= mv_new->co[0]= mv_orig->co[0];
401                                         vc->co[1]= mv_new->co[1]= mv_orig->co[1];
402                                         vc->co[2]= mv_new->co[2]= mv_orig->co[2];
403
404                                         vc->flag= 0;
405                                         vc->e[0]= vc->e[1]= NULL;
406                                         vc->v[0]= vc->v[1]= -1;
407
408                                         /* length in 2d, dont sqrt because this is only for comparison */
409                                         vc->dist =      vc->co[other_axis_1]*vc->co[other_axis_1] +
410                                                                 vc->co[other_axis_2]*vc->co[other_axis_2];
411
412                                         /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
413                                 }
414                         }
415
416                         /* this loop builds connectivity info for verts */
417                         for (i=0; i<totedge; i++, med_new++) {
418                                 vc= &vert_connect[med_new->v1];
419
420                                 if (vc->v[0] == -1) { /* unused */
421                                         vc->v[0]= med_new->v2;
422                                         vc->e[0]= med_new;
423                                 }
424                                 else if (vc->v[1] == -1) {
425                                         vc->v[1]= med_new->v2;
426                                         vc->e[1]= med_new;
427                                 }
428                                 else {
429                                         vc->v[0]= vc->v[1]= -2; /* erro value  - dont use, 3 edges on vert */
430                                 }
431
432                                 vc= &vert_connect[med_new->v2];
433
434                                 /* same as above but swap v1/2 */
435                                 if (vc->v[0] == -1) { /* unused */
436                                         vc->v[0]= med_new->v1;
437                                         vc->e[0]= med_new;
438                                 }
439                                 else if (vc->v[1] == -1) {
440                                         vc->v[1]= med_new->v1;
441                                         vc->e[1]= med_new;
442                                 }
443                                 else {
444                                         vc->v[0]= vc->v[1]= -2; /* erro value  - dont use, 3 edges on vert */
445                                 }
446                         }
447
448                         /* find the first vert */
449                         vc= vert_connect;
450                         for (i=0; i < totvert; i++, vc++) {
451                                 /* Now do search for connected verts, order all edges and flip them
452                                  * so resulting faces are flipped the right way */
453                                 vc_tot_linked= 0; /* count the number of linked verts for this loop */
454                                 if (vc->flag == 0) {
455                                         int v_best=-1, ed_loop_closed=0; /* vert and vert new */
456                                         ScrewVertIter lt_iter;
457                                         int ed_loop_flip= 0; /* compiler complains if not initialized, but it should be initialized below */
458                                         float fl= -1.0f;
459
460                                         /*printf("Loop on connected vert: %i\n", i);*/
461
462                                         for(j=0; j<2; j++) {
463                                                 /*printf("\tSide: %i\n", j);*/
464                                                 screwvert_iter_init(&lt_iter, vert_connect, i, j);
465                                                 if (j == 1) {
466                                                         screwvert_iter_step(&lt_iter);
467                                                 }
468                                                 while (lt_iter.v_poin) {
469                                                         /*printf("\t\tVERT: %i\n", lt_iter.v);*/
470                                                         if (lt_iter.v_poin->flag) {
471                                                                 /*printf("\t\t\tBreaking Found end\n");*/
472                                                                 //endpoints[0]= endpoints[1]= -1;
473                                                                 ed_loop_closed= 1; /* circle */
474                                                                 break;
475                                                         }
476                                                         lt_iter.v_poin->flag= 1;
477                                                         vc_tot_linked++;
478                                                         /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/
479                                                         if (fl <= lt_iter.v_poin->dist) {
480                                                                 fl= lt_iter.v_poin->dist;
481                                                                 v_best= lt_iter.v;
482                                                                 /*printf("\t\t\tVERT BEST: %i\n", v_best);*/
483                                                         }
484                                                         screwvert_iter_step(&lt_iter);
485                                                         if (!lt_iter.v_poin) {
486                                                                 /*printf("\t\t\tFound End Also Num %i\n", j);*/
487                                                                 /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */
488                                                                 break;
489                                                         }
490                                                 }
491                                         }
492
493                                         /* now we have a collection of used edges. flip their edges the right way*/
494                                         /*if (v_best != -1) - */
495
496                                         /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/
497
498                                         if (vc_tot_linked>1) {
499                                                 float vf_1, vf_2, vf_best;
500
501                                                 vc_tmp= &vert_connect[v_best];
502
503                                                 tmpf1= vert_connect[vc_tmp->v[0]].co;
504                                                 tmpf2= vert_connect[vc_tmp->v[1]].co;
505
506
507                                                 /* edge connects on each side! */
508                                                 if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) {
509                                                         /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
510                                                         /* find out which is higher */
511
512                                                         vf_1= tmpf1[ltmd->axis];
513                                                         vf_2= tmpf2[ltmd->axis];
514                                                         vf_best= vc_tmp->co[ltmd->axis];
515
516                                                         if (vf_1 < vf_best && vf_best < vf_2) {
517                                                                 ed_loop_flip= 0;
518                                                         }
519                                                         else if (vf_1 > vf_best && vf_best > vf_2) {
520                                                                 ed_loop_flip= 1;
521                                                         }
522                                                         else {
523                                                                 /* not so simple to work out which edge is higher */
524                                                                 sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co);
525                                                                 sub_v3_v3v3(tmp_vec2, tmpf2, vc_tmp->co);
526                                                                 normalize_v3(tmp_vec1);
527                                                                 normalize_v3(tmp_vec2);
528
529                                                                 if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) {
530                                                                         ed_loop_flip= 1;
531                                                                 }
532                                                                 else {
533                                                                         ed_loop_flip= 0;
534                                                                 }
535                                                         }
536                                                 }
537                                                 else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */
538                                                         /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
539                                                         if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
540                                                                 ed_loop_flip= 1;
541                                                         }
542                                                         else { /* best is below or even... in even case we cant know whet  to do. */
543                                                                 ed_loop_flip= 0;
544                                                         }
545
546                                                 }/* else {
547                                                         printf("No Connected ___\n");
548                                                 }*/
549
550                                                 /*printf("flip direction %i\n", ed_loop_flip);*/
551
552
553                                                 /* switch the flip option if set
554                                                  * note: flip is now done at face level so copying vgroup slizes is easier */
555                                                 /*                                              
556                                                 if (do_flip)
557                                                         ed_loop_flip= !ed_loop_flip;
558                                                 */
559
560                                                 if (angle < 0.0f)
561                                                         ed_loop_flip= !ed_loop_flip;
562
563                                                 /* if its closed, we only need 1 loop */
564                                                 for(j=ed_loop_closed; j<2; j++) {
565                                                         /*printf("Ordering Side J %i\n", j);*/
566
567                                                         screwvert_iter_init(&lt_iter, vert_connect, v_best, j);
568                                                         /*printf("\n\nStarting - Loop\n");*/
569                                                         lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */
570
571
572                                                         /* If this is the vert off the best vert and
573                                                          * the best vert has 2 edges connected too it
574                                                          * then swap the flip direction */
575                                                         if (j == 1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1))
576                                                                 ed_loop_flip= !ed_loop_flip;
577
578                                                         while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
579                                                                 /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/
580
581                                                                 lt_iter.v_poin->flag= 2;
582                                                                 if (lt_iter.e) {
583                                                                         if (lt_iter.v == lt_iter.e->v1) {
584                                                                                 if (ed_loop_flip == 0) {
585                                                                                         /*printf("\t\t\tFlipping 0\n");*/
586                                                                                         SWAP(unsigned int, lt_iter.e->v1, lt_iter.e->v2);
587                                                                                 }/* else {
588                                                                                         printf("\t\t\tFlipping Not 0\n");
589                                                                                 }*/
590                                                                         }
591                                                                         else if (lt_iter.v == lt_iter.e->v2) {
592                                                                                 if (ed_loop_flip == 1) {
593                                                                                         /*printf("\t\t\tFlipping 1\n");*/
594                                                                                         SWAP(unsigned int, lt_iter.e->v1, lt_iter.e->v2);
595                                                                                 }/* else {
596                                                                                         printf("\t\t\tFlipping Not 1\n");
597                                                                                 }*/
598                                                                         }/* else {
599                                                                                 printf("\t\tIncorrect edge topology");
600                                                                         }*/
601                                                                 }/* else {
602                                                                         printf("\t\tNo Edge at this point\n");
603                                                                 }*/
604                                                                 screwvert_iter_step(&lt_iter);
605                                                         }
606                                                 }
607                                         }
608                                 }
609
610                                 /* *VERTEX NORMALS*
611                                  * we know the surrounding edges are ordered correctly now
612                                  * so its safe to create vertex normals.
613                                  *
614                                  * calculate vertex normals that can be propagated on lathing
615                                  * use edge connectivity work this out */
616                                 if (vc->v[0] >= 0) {
617                                         if (vc->v[1] >= 0) {
618                                                 /* 2 edges connedted */
619                                                 /* make 2 connecting vert locations relative to the middle vert */
620                                                 sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
621                                                 sub_v3_v3v3(tmp_vec2, mvert_new[vc->v[1]].co, mvert_new[i].co);
622                                                 /* normalize so both edges have the same influence, no matter their length */
623                                                 normalize_v3(tmp_vec1);
624                                                 normalize_v3(tmp_vec2);
625
626                                                 /* vc_no_tmp1 - this line is the average direction of both connecting edges
627                                                  *
628                                                  * Use the edge order to make the subtraction, flip the normal the right way
629                                                  * edge should be there but check just in case... */
630                                                 if (vc->e && vc->e[0]->v1 == i) {
631                                                         sub_v3_v3(tmp_vec1, tmp_vec2);
632                                                 }
633                                                 else {
634                                                         sub_v3_v3v3(tmp_vec1, tmp_vec2, tmp_vec1);
635                                                 }
636                                         }
637                                         else {
638                                                 /* only 1 edge connected - same as above except
639                                                  * dont need to average edge direction */
640                                                 if (vc->e && vc->e[0]->v2 == i) {
641                                                         sub_v3_v3v3(tmp_vec1, mvert_new[i].co, mvert_new[vc->v[0]].co);
642                                                 }
643                                                 else {
644                                                         sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
645                                                 }
646                                         }
647
648                                         /* vc_no_tmp2 - is a line 90d from the pivot to the vec
649                                          * This is used so the resulting normal points directly away from the middle */
650                                         cross_v3_v3v3(tmp_vec2, axis_vec, vc->co);
651
652                                         /* edge average vector and right angle to the pivot make the normal */
653                                         cross_v3_v3v3(vc->no, tmp_vec1, tmp_vec2);
654
655                                 }
656                                 else {
657                                         copy_v3_v3(vc->no, vc->co);
658                                 }
659
660                                 /* we wont be looping on this data again so copy normals here */
661                                 if (angle < 0.0f)
662                                         negate_v3(vc->no);
663
664                                 normalize_v3(vc->no);
665                                 normal_float_to_short_v3(mvert_new[i].no, vc->no);
666
667                                 /* Done with normals */
668                         }
669                 }
670         }
671         else {
672                 mv_orig= mvert_orig;
673                 mv_new= mvert_new;
674
675                 for (i=0; i < totvert; i++, mv_new++, mv_orig++) {
676                         copy_v3_v3(mv_new->co, mv_orig->co);
677                 }
678         }
679         /* done with edge connectivity based normal flipping */
680         
681         /* Add Faces */
682         for (step=1; step < step_tot; step++) {
683                 const int varray_stride= totvert * step;
684                 float step_angle;
685                 float nor_tx[3];
686                 float mat[4][4];
687                 /* Rotation Matrix */
688                 step_angle= (angle / (step_tot - (!close))) * step;
689
690                 if (ltmd->ob_axis) {
691                         axis_angle_to_mat3(mat3, axis_vec, step_angle);
692                         copy_m4_m3(mat, mat3);
693                 }
694                 else {
695                         unit_m4(mat);
696                         rotate_m4(mat, axis_char, step_angle);
697                         copy_m3_m4(mat3, mat);
698                 }
699
700                 if(screw_ofs)
701                         madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)step / (float)(step_tot-1)));
702
703                 /* copy a slice */
704                 DM_copy_vert_data(dm, result, 0, varray_stride, totvert);
705                 
706                 mv_new_base= mvert_new;
707                 mv_new= &mvert_new[varray_stride]; /* advance to the next slice */
708                 
709                 for (j=0; j<totvert; j++, mv_new_base++, mv_new++) {
710                         /* set normal */
711                         if(vert_connect) {
712                                 mul_v3_m3v3(nor_tx, mat3, vert_connect[j].no);
713
714                                 /* set the normal now its transformed */
715                                 normal_float_to_short_v3(mv_new->no, nor_tx);
716                         }
717                         
718                         /* set location */
719                         copy_v3_v3(mv_new->co, mv_new_base->co);
720                         
721                         /* only need to set these if using non cleared memory */
722                         /*mv_new->mat_nr= mv_new->flag= 0;*/
723                                 
724                         if (ltmd->ob_axis) {
725                                 sub_v3_v3(mv_new->co, mtx_tx[3]);
726
727                                 mul_m4_v3(mat, mv_new->co);
728
729                                 add_v3_v3(mv_new->co, mtx_tx[3]);
730                         }
731                         else {
732                                 mul_m4_v3(mat, mv_new->co);
733                         }
734                         
735                         /* add the new edge */
736                         med_new->v1= varray_stride + j;
737                         med_new->v2= med_new->v1 - totvert;
738                         med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
739                         med_new++;
740                 }
741         }
742
743         /* we can avoid if using vert alloc trick */
744         if(vert_connect) {
745                 MEM_freeN(vert_connect);
746                 vert_connect= NULL;
747         }
748
749         if (close) {
750                 /* last loop of edges, previous loop dosnt account for the last set of edges */
751                 const int varray_stride= (step_tot - 1) * totvert;
752
753                 for (i=0; i<totvert; i++) {
754                         med_new->v1= i;
755                         med_new->v2= varray_stride + i;
756                         med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
757                         med_new++;
758                 }
759         }
760         
761         mp_new= mpoly_new;
762         ml_new= mloop_new;
763         med_new_firstloop= medge_new;
764         
765         /* more of an offset in this case */
766         edge_offset = totedge + (totvert * (step_tot - (close ? 0 : 1)));
767
768         for (i=0; i < totedge; i++, med_new_firstloop++) {
769                 /* for each edge, make a cylinder of quads */
770                 i1= med_new_firstloop->v1;
771                 i2= med_new_firstloop->v2;
772
773                 for (step=0; step < step_tot-1; step++) {
774                         
775                         /* new face */
776                         if(do_flip) {
777                                 ml_new[3].v = i1;
778                                 ml_new[2].v = i2;
779                                 ml_new[1].v = i2 + totvert;
780                                 ml_new[0].v = i1 + totvert;
781
782                                 ml_new[2].e = step == 0 ? i : (edge_offset + step + (i * (step_tot - 1))) - 1;
783                                 ml_new[1].e = totedge + i2;
784                                 ml_new[0].e = edge_offset + step + (i * (step_tot - 1));
785                                 ml_new[3].e = totedge + i1;
786                         }
787                         else {
788                                 ml_new[0].v = i1;
789                                 ml_new[1].v = i2;
790                                 ml_new[2].v = i2 + totvert;
791                                 ml_new[3].v = i1 + totvert;
792
793                                 ml_new[0].e = step == 0 ? i : (edge_offset + step + (i * (step_tot - 1))) - 1;
794                                 ml_new[1].e = totedge + i2;
795                                 ml_new[2].e = edge_offset + step + (i * (step_tot - 1));
796                                 ml_new[3].e = totedge + i1;
797                         }
798
799
800                         mp_new->loopstart = mpoly_index * 4;
801                         mp_new->totloop = 4;
802                         mp_new->flag= ME_SMOOTH;
803                         origindex[mpoly_index]= ORIGINDEX_NONE;
804                         mp_new++;
805                         ml_new += 4;
806                         mpoly_index++;
807                         
808                         /* new vertical edge */
809                         if (step) { /* The first set is already dome */
810                                 med_new->v1= i1;
811                                 med_new->v2= i2;
812                                 med_new->flag= med_new_firstloop->flag;
813                                 med_new->crease= med_new_firstloop->crease;
814                                 med_new++;
815                         }
816                         i1 += totvert;
817                         i2 += totvert;
818                 }
819                 
820                 /* close the loop*/
821                 if (close) { 
822                         if(do_flip) {
823                                 ml_new[3].v = i1;
824                                 ml_new[2].v = i2;
825                                 ml_new[1].v = med_new_firstloop->v2;
826                                 ml_new[0].v = med_new_firstloop->v1;
827
828                                 ml_new[2].e = (edge_offset + step + (i * (step_tot - 1))) - 1;
829                                 ml_new[1].e = totedge + i2;
830                                 ml_new[0].e = i;
831                                 ml_new[3].e = totedge + i1;
832                         }
833                         else {
834                                 ml_new[0].v = i1;
835                                 ml_new[1].v = i2;
836                                 ml_new[2].v = med_new_firstloop->v2;
837                                 ml_new[3].v = med_new_firstloop->v1;
838
839                                 ml_new[0].e = (edge_offset + step + (i * (step_tot - 1))) - 1;
840                                 ml_new[1].e = totedge + i2;
841                                 ml_new[2].e = i;
842                                 ml_new[3].e = totedge + i1;
843                         }
844
845                         mp_new->loopstart = mpoly_index * 4;
846                         mp_new->totloop = 4;
847                         mp_new->flag= ME_SMOOTH;
848                         origindex[mpoly_index]= ORIGINDEX_NONE;
849                         mp_new++;
850                         ml_new += 4;
851                         mpoly_index++;
852                 }
853                 
854                 /* new vertical edge */
855                 med_new->v1= i1;
856                 med_new->v2= i2;
857                 med_new->flag= med_new_firstloop->flag & ~ME_LOOSEEDGE;
858                 med_new->crease= med_new_firstloop->crease;
859                 med_new++;
860         }
861
862         /* validate loop edges */
863 #if 0
864         {
865                 i = 0;
866                 printf("\n");
867                 for ( ; i < maxPolys * 4; i += 4) {
868                         int ii;
869                         ml_new = mloop_new + i;
870                         ii = findEd(medge_new, maxEdges, ml_new[0].v, ml_new[1].v);
871                         printf("%d %d -- ", ii, ml_new[0].e);
872                         ml_new[0].e = ii;
873
874                         ii = findEd(medge_new, maxEdges, ml_new[1].v, ml_new[2].v);
875                         printf("%d %d -- ", ii, ml_new[1].e);
876                         ml_new[1].e = ii;
877
878                         ii = findEd(medge_new, maxEdges, ml_new[2].v, ml_new[3].v);
879                         printf("%d %d -- ", ii, ml_new[2].e);
880                         ml_new[2].e = ii;
881
882                         ii = findEd(medge_new, maxEdges, ml_new[3].v, ml_new[0].v);
883                         printf("%d %d\n", ii, ml_new[3].e);
884                         ml_new[3].e = ii;
885
886                 }
887         }
888 #endif
889
890         if((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) {
891                 /* BMESH_TODO, we only need to get vertex normals here, this is way overkill */
892                 CDDM_calc_normals(result);
893         }
894
895         return result;
896 }
897
898
899 static void updateDepgraph(ModifierData *md, DagForest *forest,
900                                                 struct Scene *UNUSED(scene),
901                                                 Object *UNUSED(ob),
902                                                 DagNode *obNode)
903 {
904         ScrewModifierData *ltmd= (ScrewModifierData*) md;
905
906         if(ltmd->ob_axis) {
907                 DagNode *curNode= dag_get_node(forest, ltmd->ob_axis);
908
909                 dag_add_relation(forest, curNode, obNode,
910                                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
911                                                  "Screw Modifier");
912         }
913 }
914
915 static void foreachObjectLink(
916                                 ModifierData *md, Object *ob,
917                                 void (*walk)(void *userData, Object *ob, Object **obpoin),
918                                 void *userData)
919 {
920         ScrewModifierData *ltmd= (ScrewModifierData*) md;
921
922         walk(userData, ob, &ltmd->ob_axis);
923 }
924
925 /* This dosnt work with material*/
926 static DerivedMesh *applyModifierEM(
927                                                 ModifierData *md,
928                                                 Object *ob,
929                                                 struct BMEditMesh *UNUSED(editData),
930                                                 DerivedMesh *derivedData)
931 {
932         return applyModifier(md, ob, derivedData, 0, 1);
933 }
934
935 static int dependsOnTime(ModifierData *UNUSED(md))
936 {
937         return 0;
938 }
939
940
941 ModifierTypeInfo modifierType_Screw = {
942         /* name */              "Screw",
943         /* structName */        "ScrewModifierData",
944         /* structSize */        sizeof(ScrewModifierData),
945         /* type */              eModifierTypeType_Constructive,
946
947         /* flags */             eModifierTypeFlag_AcceptsMesh
948                                                         | eModifierTypeFlag_AcceptsCVs
949                                                         | eModifierTypeFlag_SupportsEditmode
950                                                         | eModifierTypeFlag_EnableInEditmode,
951
952         /* copyData */          copyData,
953         /* deformVerts */       NULL,
954         /* deformMatrices */    NULL,
955         /* deformVertsEM */     NULL,
956         /* deformMatricesEM */  NULL,
957         /* applyModifier */     applyModifier,
958         /* applyModifierEM */   applyModifierEM,
959         /* initData */          initData,
960         /* requiredDataMask */  NULL,
961         /* freeData */          NULL,
962         /* isDisabled */        NULL,
963         /* updateDepgraph */    updateDepgraph,
964         /* dependsOnTime */     dependsOnTime,
965         /* dependsOnNormals */  NULL,
966         /* foreachObjectLink */ foreachObjectLink,
967         /* foreachIDLink */     NULL,
968         /* foreachTexLink */    NULL,
969 };