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