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