4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
23 * Contributor(s): Daniel Dunbar
29 * ***** END GPL LICENSE BLOCK *****
33 /* Screw modifier: revolves the edges about an axis */
35 #include "DNA_meshdata_types.h"
36 #include "DNA_object_types.h"
40 #include "BKE_utildefines.h"
41 #include "BKE_cdderivedmesh.h"
43 #include "depsgraph_private.h"
44 #include "MOD_modifiertypes.h"
45 #include "MEM_guardedalloc.h"
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 */
57 typedef struct ScrewVertIter {
58 ScrewVertConnect * v_array;
59 ScrewVertConnect * v_poin;
66 static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, int v_init, int dir)
68 iter->v_array = array;
72 iter->v_poin = &array[v_init];
73 iter->v_other = iter->v_poin->v[dir];
74 iter->e = iter->v_poin->e[!dir];
83 static void screwvert_iter_step(ScrewVertIter *iter)
85 if (iter->v_poin->v[0] == iter->v_other) {
86 iter->v_other= iter->v;
87 iter->v= iter->v_poin->v[1];
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];
94 iter->v_poin= &iter->v_array[iter->v];
95 iter->e= iter->v_poin->e[(iter->v_poin->e[0] == iter->e)];
104 static void initData(ModifierData *md)
106 ScrewModifierData *ltmd= (ScrewModifierData*) md;
108 ltmd->angle= M_PI * 2.0;
112 ltmd->render_steps= 16;
116 static void copyData(ModifierData *md, ModifierData *target)
118 ScrewModifierData *sltmd= (ScrewModifierData*) md;
119 ScrewModifierData *tltmd= (ScrewModifierData*) target;
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;
131 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
132 DerivedMesh *derivedData,
134 int UNUSED(isFinalCalc))
136 DerivedMesh *dm= derivedData;
138 ScrewModifierData *ltmd= (ScrewModifierData*) md;
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);
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];
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];
161 int vc_tot_linked= 0;
162 short other_axis_1, other_axis_2;
163 float *tmpf1, *tmpf2;
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;
169 ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL;
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}};
176 /* dont do anything? */
178 return CDDM_from_template(dm, 0, 0, 0);
180 step_tot= useRenderParams ? ltmd->render_steps : ltmd->steps;
191 default: /* 2, use default to quiet warnings */
197 axis_vec[ltmd->axis]= 1.0f;
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);
205 /* calc the axis vec */
206 mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */
207 normalize_v3(axis_vec);
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]);
215 float zero[3]={0.0f, 0.0f, 0.0f};
217 screw_ofs= closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
226 #if 0 // cant incluide this, not pradictable enough, though quite fun,.
227 if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
229 copy_m3_m4(mtx3_tx, mtx_tx);
231 float vec[3] = {0,1,0};
234 cross_v3_v3v3(cross1, vec, axis_vec);
236 mul_v3_m3v3(cross2, mtx3_tx, cross1);
242 cross_v3_v3v3(c1, cross2, axis_vec);
243 cross_v3_v3v3(c2, axis_vec, c1);
246 angle= angle_v3v3(cross1, c2);
248 cross_v3_v3v3(axis_tmp, cross1, c2);
249 normalize_v3(axis_tmp);
251 if(len_v3v3(axis_tmp, axis_vec) > 1.0f)
259 /* exis char is used by i_rotate*/
260 axis_char += ltmd->axis; /* 'X' + axis */
262 /* useful to be able to use the axis vec in some cases still */
264 axis_vec[ltmd->axis]= 1.0f;
267 /* apply the multiplier */
269 screw_ofs *= ltmd->iter;
271 /* multiplying the steps is a bit tricky, this works best */
272 step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
274 /* will the screw be closed?
275 * Note! smaller then FLT_EPSILON*100 gives problems with float precission so its never closed. */
276 if (fabs(screw_ofs) <= (FLT_EPSILON*100) && fabs(fabs(angle) - (M_PI * 2)) <= (FLT_EPSILON*100)) {
279 if(step_tot < 2) step_tot= 2;
281 maxVerts = totvert * step_tot; /* -1 because we're joining back up */
282 maxEdges = (totvert * step_tot) + /* these are the edges between new verts */
283 (totedge * step_tot); /* -1 because vert edges join */
284 maxFaces = totedge * step_tot;
290 if(step_tot < 2) step_tot= 2;
292 maxVerts = totvert * step_tot; /* -1 because we're joining back up */
293 maxEdges = (totvert * (step_tot-1)) + /* these are the edges between new verts */
294 (totedge * step_tot); /* -1 because vert edges join */
295 maxFaces = totedge * (step_tot-1);
298 result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces);
300 /* copy verts from mesh */
301 mvert_orig = dm->getVertArray(dm);
302 medge_orig = dm->getEdgeArray(dm);
304 mvert_new = result->getVertArray(result);
305 mface_new = result->getFaceArray(result);
306 medge_new = result->getEdgeArray(result);
308 origindex= result->getFaceDataArray(result, CD_ORIGINDEX);
310 DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */
312 /* Set the locations of the first set of verts */
317 /* Copy the first set of edges */
318 med_orig= medge_orig;
320 for (i=0; i < totedge; i++, med_orig++, med_new++) {
321 med_new->v1= med_orig->v1;
322 med_new->v2= med_orig->v2;
323 med_new->crease= med_orig->crease;
324 med_new->flag= med_orig->flag & ~ME_LOOSEEDGE;
327 if(ltmd->flag & MOD_SCREW_NORMAL_CALC) {
329 * Normal Calculation (for face flipping)
330 * Sort edge verts for correct face flipping
331 * NOT REALLY NEEDED but face flipping is nice.
338 * Since we are only ordering the edges here it can avoid mallocing the
339 * extra space by abusing the vert array berfore its filled with new verts.
340 * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert
341 * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3
342 * so its safe to use the second 2 thrids of MVert the array for vert_connect,
343 * just make sure ScrewVertConnect struct is no more then twice as big as MVert,
344 * at the moment there is no chance of that being a problem,
345 * unless MVert becomes half its current size.
347 * once the edges are ordered, vert_connect is not needed and it can be used for verts
349 * This makes the modifier faster with one less alloc.
352 vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect");
353 //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */
356 /* Copy Vert Locations */
357 /* - We can do this in a later loop - only do here if no normal calc */
359 for (i=0; i < totvert; i++, mv_orig++, mv_new++) {
360 copy_v3_v3(mv_new->co, mv_orig->co);
361 normalize_v3_v3(vc->no, mv_new->co); /* no edges- this is realy a dummy normal */
365 /*printf("\n\n\n\n\nStarting Modifier\n");*/
371 /*mtx_tx is initialized early on */
372 for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
373 vc->co[0]= mv_new->co[0]= mv_orig->co[0];
374 vc->co[1]= mv_new->co[1]= mv_orig->co[1];
375 vc->co[2]= mv_new->co[2]= mv_orig->co[2];
378 vc->e[0]= vc->e[1]= NULL;
379 vc->v[0]= vc->v[1]= -1;
381 mul_m4_v3(mtx_tx, vc->co);
382 /* length in 2d, dont sqrt because this is only for comparison */
383 vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] +
384 vc->co[other_axis_2]*vc->co[other_axis_2];
386 /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
390 for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) {
391 vc->co[0]= mv_new->co[0]= mv_orig->co[0];
392 vc->co[1]= mv_new->co[1]= mv_orig->co[1];
393 vc->co[2]= mv_new->co[2]= mv_orig->co[2];
396 vc->e[0]= vc->e[1]= NULL;
397 vc->v[0]= vc->v[1]= -1;
399 /* length in 2d, dont sqrt because this is only for comparison */
400 vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] +
401 vc->co[other_axis_2]*vc->co[other_axis_2];
403 /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/
407 /* this loop builds connectivity info for verts */
408 for (i=0; i<totedge; i++, med_new++) {
409 vc= &vert_connect[med_new->v1];
411 if (vc->v[0] == -1) { /* unused */
412 vc->v[0]= med_new->v2;
415 else if (vc->v[1] == -1) {
416 vc->v[1]= med_new->v2;
420 vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */
423 vc= &vert_connect[med_new->v2];
425 /* same as above but swap v1/2 */
426 if (vc->v[0] == -1) { /* unused */
427 vc->v[0]= med_new->v1;
430 else if (vc->v[1] == -1) {
431 vc->v[1]= med_new->v1;
435 vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */
439 /* find the first vert */
441 for (i=0; i < totvert; i++, vc++) {
442 int v_best=-1, ed_loop_closed=0; /* vert and vert new */
443 int ed_loop_flip= 0; /* compiler complains if not initialized, but it should be initialized below */
445 ScrewVertIter lt_iter;
447 /* Now do search for connected verts, order all edges and flip them
448 * so resulting faces are flipped the right way */
449 vc_tot_linked= 0; /* count the number of linked verts for this loop */
451 /*printf("Loop on connected vert: %i\n", i);*/
454 /*printf("\tSide: %i\n", j);*/
455 screwvert_iter_init(<_iter, vert_connect, i, j);
457 screwvert_iter_step(<_iter);
459 while (lt_iter.v_poin) {
460 /*printf("\t\tVERT: %i\n", lt_iter.v);*/
461 if (lt_iter.v_poin->flag) {
462 /*printf("\t\t\tBreaking Found end\n");*/
463 //endpoints[0]= endpoints[1]= -1;
464 ed_loop_closed= 1; /* circle */
467 lt_iter.v_poin->flag= 1;
469 /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/
470 if (fl <= lt_iter.v_poin->dist) {
471 fl= lt_iter.v_poin->dist;
473 /*printf("\t\t\tVERT BEST: %i\n", v_best);*/
475 screwvert_iter_step(<_iter);
476 if (!lt_iter.v_poin) {
477 /*printf("\t\t\tFound End Also Num %i\n", j);*/
478 /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */
484 /* now we have a collection of used edges. flip their edges the right way*/
485 /*if (v_best != -1) - */
487 /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/
489 if (vc_tot_linked>1) {
490 float vf_1, vf_2, vf_best;
492 vc_tmp= &vert_connect[v_best];
494 tmpf1= vert_connect[vc_tmp->v[0]].co;
495 tmpf2= vert_connect[vc_tmp->v[1]].co;
498 /* edge connects on each side! */
499 if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) {
500 /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
501 /* find out which is higher */
503 vf_1= tmpf1[ltmd->axis];
504 vf_2= tmpf2[ltmd->axis];
505 vf_best= vc_tmp->co[ltmd->axis];
507 if (vf_1 < vf_best && vf_best < vf_2) {
510 else if (vf_1 > vf_best && vf_best > vf_2) {
514 /* not so simple to work out which edge is higher */
515 sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co);
516 sub_v3_v3v3(tmp_vec2, tmpf2, vc_tmp->co);
517 normalize_v3(tmp_vec1);
518 normalize_v3(tmp_vec2);
520 if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) {
528 else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */
529 /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
530 if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
533 else { /* best is below or even... in even case we cant know whet to do. */
538 printf("No Connected ___\n");
541 /*printf("flip direction %i\n", ed_loop_flip);*/
544 /* switch the flip option if set
545 * note: flip is now done at face level so copying vgroup slizes is easier */
548 ed_loop_flip= !ed_loop_flip;
552 ed_loop_flip= !ed_loop_flip;
554 /* if its closed, we only need 1 loop */
555 for(j=ed_loop_closed; j<2; j++) {
556 /*printf("Ordering Side J %i\n", j);*/
558 screwvert_iter_init(<_iter, vert_connect, v_best, j);
559 /*printf("\n\nStarting - Loop\n");*/
560 lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */
563 /* If this is the vert off the best vert and
564 * the best vert has 2 edges connected too it
565 * then swap the flip direction */
566 if (j == 1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1))
567 ed_loop_flip= !ed_loop_flip;
569 while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
570 /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/
572 lt_iter.v_poin->flag= 2;
574 if (lt_iter.v == lt_iter.e->v1) {
575 if (ed_loop_flip == 0) {
576 /*printf("\t\t\tFlipping 0\n");*/
577 SWAP(int, lt_iter.e->v1, lt_iter.e->v2);
579 printf("\t\t\tFlipping Not 0\n");
582 else if (lt_iter.v == lt_iter.e->v2) {
583 if (ed_loop_flip == 1) {
584 /*printf("\t\t\tFlipping 1\n");*/
585 SWAP(int, lt_iter.e->v1, lt_iter.e->v2);
587 printf("\t\t\tFlipping Not 1\n");
590 printf("\t\tIncorrect edge topology");
593 printf("\t\tNo Edge at this point\n");
595 screwvert_iter_step(<_iter);
602 * we know the surrounding edges are ordered correctly now
603 * so its safe to create vertex normals.
605 * calculate vertex normals that can be propodated on lathing
606 * use edge connectivity work this out */
609 /* 2 edges connedted */
610 /* make 2 connecting vert locations relative to the middle vert */
611 sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
612 sub_v3_v3v3(tmp_vec2, mvert_new[vc->v[1]].co, mvert_new[i].co);
613 /* normalize so both edges have the same influence, no matter their length */
614 normalize_v3(tmp_vec1);
615 normalize_v3(tmp_vec2);
617 /* vc_no_tmp1 - this line is the average direction of both connecting edges
619 * Use the edge order to make the subtraction, flip the normal the right way
620 * edge should be there but check just in case... */
621 if (vc->e && vc->e[0]->v1 == i) {
622 sub_v3_v3(tmp_vec1, tmp_vec2);
625 sub_v3_v3v3(tmp_vec1, tmp_vec2, tmp_vec1);
629 /* only 1 edge connected - same as above except
630 * dont need to average edge direction */
631 if (vc->e && vc->e[0]->v2 == i) {
632 sub_v3_v3v3(tmp_vec1, mvert_new[i].co, mvert_new[vc->v[0]].co);
635 sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
639 /* vc_no_tmp2 - is a line 90d from the pivot to the vec
640 * This is used so the resulting normal points directly away from the middle */
641 cross_v3_v3v3(tmp_vec2, axis_vec, vc->co);
643 /* edge average vector and right angle to the pivot make the normal */
644 cross_v3_v3v3(vc->no, tmp_vec1, tmp_vec2);
648 copy_v3_v3(vc->no, vc->co);
651 /* we wont be looping on this data again so copy normals here */
655 normalize_v3(vc->no);
656 normal_float_to_short_v3(mvert_new[i].no, vc->no);
658 /* Done with normals */
666 for (i=0; i < totvert; i++, mv_new++, mv_orig++) {
667 copy_v3_v3(mv_new->co, mv_orig->co);
670 /* done with edge connectivity based normal flipping */
673 for (step=1; step < step_tot; step++) {
674 const int varray_stride= totvert * step;
677 /* Rotation Matrix */
678 step_angle= (angle / (step_tot - (!close))) * step;
681 axis_angle_to_mat3(mat3, axis_vec, step_angle);
682 copy_m4_m3(mat, mat3);
686 rotate_m4(mat, axis_char, step_angle);
687 copy_m3_m4(mat3, mat);
691 madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)step / (float)(step_tot-1)));
694 DM_copy_vert_data(dm, result, 0, varray_stride, totvert);
696 mv_new_base= mvert_new;
697 mv_new= &mvert_new[varray_stride]; /* advance to the next slice */
699 for (j=0; j<totvert; j++, mv_new_base++, mv_new++) {
702 mul_v3_m3v3(nor_tx, mat3, vert_connect[j].no);
704 /* set the normal now its transformed */
705 normal_float_to_short_v3(mv_new->no, nor_tx);
709 copy_v3_v3(mv_new->co, mv_new_base->co);
711 /* only need to set these if using non cleared memory */
712 /*mv_new->mat_nr= mv_new->flag= 0;*/
715 sub_v3_v3(mv_new->co, mtx_tx[3]);
717 mul_m4_v3(mat, mv_new->co);
719 add_v3_v3(mv_new->co, mtx_tx[3]);
722 mul_m4_v3(mat, mv_new->co);
725 /* add the new edge */
726 med_new->v1= varray_stride + j;
727 med_new->v2= med_new->v1 - totvert;
728 med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
733 /* we can avoid if using vert alloc trick */
735 MEM_freeN(vert_connect);
740 /* last loop of edges, previous loop dosnt account for the last set of edges */
741 const int varray_stride= (step_tot - 1) * totvert;
743 for (i=0; i<totvert; i++) {
745 med_new->v2= varray_stride + i;
746 med_new->flag= ME_EDGEDRAW|ME_EDGERENDER;
752 med_new_firstloop= medge_new;
754 for (i=0; i < totedge; i++, med_new_firstloop++) {
755 /* for each edge, make a cylinder of quads */
756 i1= med_new_firstloop->v1;
757 i2= med_new_firstloop->v2;
759 for (step=0; step < step_tot-1; step++) {
765 mf_new->v2= i2 + totvert;
766 mf_new->v1= i1 + totvert;
771 mf_new->v3= i2 + totvert;
772 mf_new->v4= i1 + totvert;
775 if( !mf_new->v3 || !mf_new->v4 ) {
776 SWAP(int, mf_new->v1, mf_new->v3);
777 SWAP(int, mf_new->v2, mf_new->v4);
779 mf_new->flag= ME_SMOOTH;
780 origindex[mface_index]= ORIGINDEX_NONE;
784 /* new vertical edge */
785 if (step) { /* The first set is already dome */
788 med_new->flag= med_new_firstloop->flag;
789 med_new->crease= med_new_firstloop->crease;
801 mf_new->v2= med_new_firstloop->v2;
802 mf_new->v1= med_new_firstloop->v1;
807 mf_new->v3= med_new_firstloop->v2;
808 mf_new->v4= med_new_firstloop->v1;
811 if( !mf_new->v3 || !mf_new->v4 ) {
812 SWAP(int, mf_new->v1, mf_new->v3);
813 SWAP(int, mf_new->v2, mf_new->v4);
815 mf_new->flag= ME_SMOOTH;
816 origindex[mface_index]= ORIGINDEX_NONE;
821 /* new vertical edge */
824 med_new->flag= med_new_firstloop->flag & ~ME_LOOSEEDGE;
825 med_new->crease= med_new_firstloop->crease;
829 if((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) {
830 CDDM_calc_normals(result);
837 static void updateDepgraph(ModifierData *md, DagForest *forest,
838 struct Scene *UNUSED(scene),
842 ScrewModifierData *ltmd= (ScrewModifierData*) md;
845 DagNode *curNode= dag_get_node(forest, ltmd->ob_axis);
847 dag_add_relation(forest, curNode, obNode,
848 DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
853 static void foreachObjectLink(
854 ModifierData *md, Object *ob,
855 void (*walk)(void *userData, Object *ob, Object **obpoin),
858 ScrewModifierData *ltmd= (ScrewModifierData*) md;
860 walk(userData, ob, <md->ob_axis);
863 /* This dosnt work with material*/
864 static DerivedMesh *applyModifierEM(
867 struct EditMesh *UNUSED(editData),
868 DerivedMesh *derivedData)
870 return applyModifier(md, ob, derivedData, 0, 1);
873 static int dependsOnTime(ModifierData *UNUSED(md))
879 ModifierTypeInfo modifierType_Screw = {
881 /* structName */ "ScrewModifierData",
882 /* structSize */ sizeof(ScrewModifierData),
883 /* type */ eModifierTypeType_Constructive,
885 /* flags */ eModifierTypeFlag_AcceptsMesh
886 | eModifierTypeFlag_AcceptsCVs
887 | eModifierTypeFlag_SupportsEditmode
888 | eModifierTypeFlag_EnableInEditmode,
890 /* copyData */ copyData,
892 /* deformVertsEM */ 0,
893 /* deformMatricesEM */ 0,
894 /* applyModifier */ applyModifier,
895 /* applyModifierEM */ applyModifierEM,
896 /* initData */ initData,
897 /* requiredDataMask */ 0,
900 /* updateDepgraph */ updateDepgraph,
901 /* dependsOnTime */ dependsOnTime,
902 /* dependsOnNormals */ 0,
903 /* foreachObjectLink */ foreachObjectLink,
904 /* foreachIDLink */ 0,