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