Revision: 27653
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=27653
Author:   campbellbarton
Date:     2010-03-22 01:22:52 +0100 (Mon, 22 Mar 2010)

Log Message:
-----------
Screw Modifier (old patch was called Lathe)

didnt commit this patch because curves are generally better to create a shape 
to lathe however now that curves can have modifiers applied to them I think its 
good to have this.

Added options to offset the lathe so it can work like the screw tool as well.

- optional object for axis which also controls the center point.
- screw offset so rather then just lathing this can work more like the screw 
tool.
- screw optionally using the object distance along the axis.
- iterations so the screw can be applied multiple times.

tested to work well with curves.

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/properties_data_modifier.py
    trunk/blender/source/blender/blenkernel/intern/modifier.c
    trunk/blender/source/blender/editors/include/UI_icons.h
    trunk/blender/source/blender/editors/space_outliner/outliner.c
    trunk/blender/source/blender/makesdna/DNA_modifier_types.h
    trunk/blender/source/blender/makesrna/RNA_access.h
    trunk/blender/source/blender/makesrna/intern/rna_modifier.c

Modified: trunk/blender/release/scripts/ui/properties_data_modifier.py
===================================================================
--- trunk/blender/release/scripts/ui/properties_data_modifier.py        
2010-03-22 00:14:56 UTC (rev 27652)
+++ trunk/blender/release/scripts/ui/properties_data_modifier.py        
2010-03-22 00:22:52 UTC (rev 27653)
@@ -497,6 +497,28 @@
     def PARTICLE_SYSTEM(self, layout, ob, md, wide_ui):
         layout.label(text="See Particle panel.")
 
+    def SCREW(self, layout, ob, md, wide_ui):
+        split = layout.split()
+        
+        col = split.column()
+        col.prop(md, "axis")
+        col.prop(md, "object", text="AxisOb")
+        col.prop(md, "angle")
+        col.prop(md, "steps")
+        col.prop(md, "render_steps")
+        
+        col = split.column()
+        row = col.row()
+        row.active = (md.object is None or md.use_object_screw_offset == False)
+        row.prop(md, "screw_offset")
+        row = col.row()
+        row.active = (md.object is not None)
+        row.prop(md, "use_object_screw_offset")
+        col.prop(md, "use_normal_calculate")
+        col.prop(md, "use_normal_flip")
+        col.prop(md, "iterations")
+        
+
     def SHRINKWRAP(self, layout, ob, md, wide_ui):
         split = layout.split()
         col = split.column()

Modified: trunk/blender/source/blender/blenkernel/intern/modifier.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/modifier.c   2010-03-22 
00:14:56 UTC (rev 27652)
+++ trunk/blender/source/blender/blenkernel/intern/modifier.c   2010-03-22 
00:22:52 UTC (rev 27653)
@@ -5991,6 +5991,803 @@
        return solidifyModifier_applyModifier(md, ob, derivedData, 0, 1);
 }
 
+/* Screw */
+
+/* Screw */
+/* Screw modifier: revolves the edges about an axis
+*/
+
+/* used for gathering edge connectivity */
+typedef struct ScrewVertConnect {
+       float dist;  /* distance from the center axis */
+       float co[3]; /* loaction relative to the transformed axis */
+       float no[3]; /* calc normal of the vertex */
+       int v[2]; /* 2  verts on either side of this one */
+       MEdge *e[2]; /* edges on either side, a bit of a waste since each edge 
ref's 2 edges */
+       char flag;
+} ScrewVertConnect;
+
+typedef struct ScrewVertIter {
+       ScrewVertConnect * v_array;
+       ScrewVertConnect * v_poin;
+       int v;
+       int v_other;
+       MEdge *e;
+} ScrewVertIter;
+
+#define ScrewVertIter_INIT(iter, array, v_init, dir)\
+       iter.v_array = array;\
+       iter.v = v_init;\
+       if (v_init>=0) {\
+               iter.v_poin = &array[v_init];\
+               iter.v_other = iter.v_poin->v[dir];\
+               if (dir)\
+                       iter.e = iter.v_poin->e[0];\
+               else\
+                       iter.e = iter.v_poin->e[1];\
+       } else {\
+               iter.v_poin= NULL;\
+               iter.e= NULL;\
+       }
+
+
+#define ScrewVertIter_NEXT(iter)\
+       if (iter.v_poin->v[0] == iter.v_other) {\
+               iter.v_other= iter.v;\
+               iter.v= iter.v_poin->v[1];\
+       } else if (iter.v_poin->v[1] == iter.v_other) {\
+               iter.v_other= iter.v;\
+               iter.v= iter.v_poin->v[0];\
+       }\
+       if (iter.v >=0) {\
+               iter.v_poin= &iter.v_array[iter.v];\
+               if ( iter.v_poin->e[0] != iter.e )      iter.e= 
iter.v_poin->e[0];\
+               else                                                            
iter.e= iter.v_poin->e[1];\
+       } else {\
+               iter.e= NULL;\
+               iter.v_poin= NULL;\
+       }
+       
+static void screwModifier_initData(ModifierData *md)
+{
+       ScrewModifierData *ltmd= (ScrewModifierData*) md;
+       ltmd->ob_axis= NULL;
+       ltmd->angle= M_PI * 2.0;
+       ltmd->axis= 2;
+       ltmd->flag= 0;
+       ltmd->steps= 16;
+       ltmd->render_steps= 16;
+       ltmd->iter= 1;
+}
+
+static void screwModifier_copyData(ModifierData *md, ModifierData *target)
+{
+       ScrewModifierData *sltmd= (ScrewModifierData*) md;
+       ScrewModifierData *tltmd= (ScrewModifierData*) target;
+       
+       tltmd->ob_axis= sltmd->ob_axis;
+       tltmd->angle= sltmd->angle;
+       tltmd->axis= sltmd->axis;
+       tltmd->flag= sltmd->flag;
+       tltmd->steps= sltmd->steps;
+       tltmd->render_steps= sltmd->render_steps;
+       tltmd->iter= sltmd->iter;
+}
+
+static DerivedMesh *screwModifier_applyModifier(ModifierData *md, Object *ob,
+                                         DerivedMesh *derivedData,
+                                         int useRenderParams, int isFinalCalc)
+{
+       DerivedMesh *dm= derivedData;
+       DerivedMesh *result;
+       ScrewModifierData *ltmd= (ScrewModifierData*) md;
+       
+       int *origindex;
+       int mface_index=0;
+       int i, j;
+       int i1,i2;
+       int steps= ltmd->steps;
+       int maxVerts=0, maxEdges=0, maxFaces=0;
+       int totvert= dm->getNumVerts(dm);
+       int totedge= dm->getNumEdges(dm);
+
+       char axis_char, close;
+       float angle= ltmd->angle;
+       float screw_ofs= ltmd->screw_ofs;
+       float axis_vec[3]= {0.0f, 0.0f, 0.0f};
+       float tmp_vec1[3], tmp_vec2[3]; 
+       float mat3[3][3];
+       float mtx_tx[4][4]; /* transform the coords by an object relative to 
this objects transformation */
+       float mtx_tx_inv[4][4]; /* inverted */
+       float mtx_tmp_a[4][4];
+       
+       int vc_tot_linked= 0;
+       short other_axis_1, other_axis_2;
+       float *tmpf1, *tmpf2;
+       
+       MFace *mface_new, *mf_new;
+       MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
+       MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;
+
+       ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL;
+
+
+       float mat[4][4] =       {{0.0f, 0.0f, 0.0f, 0.0f},
+                                                {0.0f, 0.0f, 0.0f, 0.0f},
+                                                {0.0f, 0.0f, 0.0f, 0.0f},
+                                                {0.0f, 0.0f, 0.0f, 1.0f}};
+
+       /* dont do anything? */
+       if (!totvert)
+               return CDDM_from_template(dm, 0, 0, 0);
+
+       if (useRenderParams)
+               steps= ltmd->render_steps;
+       else
+               steps= ltmd->steps;
+
+       if (ltmd->axis==0) {
+               other_axis_1=1;
+               other_axis_2=2;
+       } else if (ltmd->axis==1) {
+               other_axis_1=0;
+               other_axis_2=2;
+       } else {
+               other_axis_1=0;
+               other_axis_2=1;
+       }
+
+       axis_vec[ltmd->axis]= 1.0;
+       if (ltmd->ob_axis) {
+               float mtx3_tx[3][3];
+               /* calc the matrix relative to the axis object */
+               invert_m4_m4(mtx_tmp_a, ob->obmat);
+               copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat);
+               mul_m4_m4m4(mtx_tx, mtx_tx_inv, mtx_tmp_a);
+
+               copy_m3_m4(mtx3_tx, mtx_tx);
+
+               /* calc the axis vec */
+               mul_m3_v3(mtx3_tx, axis_vec);
+               normalize_v3(axis_vec);
+
+               /* screw */
+               if(ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
+                       /* find the offset along this axis relative to this 
objects matrix */
+                       float totlen = len_v3(mtx_tx[3]);
+
+                       if(totlen != 0.0f) {
+                               float zero[3]={0,0,0};
+                               float cp[3];                            
+                               screw_ofs= closest_to_line_v3(cp, mtx_tx[3], 
zero, axis_vec);
+                       }
+                       else {
+                               screw_ofs= 0.0f;
+                       }
+               }
+
+               /* angle */
+
+#if 0  // cant incluide this, not pradictable enough, though quite fun,.
+               if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
+
+
+                       float vec[3] = {0,1,0};
+                       float cross1[3];
+                       float cross2[3];
+                       cross_v3_v3v3(cross1, vec, axis_vec);
+
+                       mul_v3_m3v3(cross2, mtx3_tx, cross1);
+                       {
+                               float c1[3];
+                               float c2[3];
+                               float axis_tmp[3];
+
+                               cross_v3_v3v3(c1, cross2, axis_vec);
+                               cross_v3_v3v3(c2, axis_vec, c1);
+
+
+                               angle= angle_v3v3(cross1, c2);
+
+                               cross_v3_v3v3(axis_tmp, cross1, c2);
+                               normalize_v3(axis_tmp);
+
+                               if(len_v3v3(axis_tmp, axis_vec) > 1.0)
+                                       angle= -angle;
+
+                       }
+               }
+#endif
+
+       } else {
+               /* exis char is used by i_rotate*/
+               axis_char= 'X' + ltmd->axis;
+
+               /* useful to be able to use the axis vec in some cases still */
+               zero_v3(axis_vec);
+               axis_vec[ltmd->axis]= 1.0;
+       }
+
+       /* apply the multiplier */
+       angle *= ltmd->iter;
+       screw_ofs *= ltmd->iter;
+
+       /* multiplying the steps is a bit tricky, this works best */
+       steps += 1;
+       steps = (steps * ltmd->iter) - (ltmd->iter - 1);
+       if(steps < 2) steps= 2;
+
+       /* will the screw be closed? */
+       if (fabs(screw_ofs) <= (FLT_EPSILON*100) && fabs(fabs(angle) -  M_PI * 
2.0) <= (FLT_EPSILON*100)) {
+               close= 1;
+       
+               maxVerts =      totvert  * steps; /* -1 because we're joining 
back up */
+               maxEdges =      (totvert * steps) + /* these are the edges 
between new verts */
+                                       (totedge * steps); /* -1 because vert 
edges join */
+               maxFaces =      totedge * steps;
+
+               screw_ofs= 0.0f;
+       } else {
+               close= 0;
+               
+               maxVerts =      totvert  * steps; /* -1 because we're joining 
back up */
+               maxEdges =      (totvert * (steps-1)) + /* these are the edges 
between new verts */
+                                       (totedge * steps); /* -1 because vert 
edges join */
+               maxFaces =      totedge * (steps-1);
+       }
+       
+       result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces);
+       
+       /* copy verts from mesh */
+       mvert_orig =    dm->getVertArray(dm);
+       medge_orig =    dm->getEdgeArray(dm);
+       
+       mvert_new =             result->getVertArray(result);
+       mface_new =             result->getFaceArray(result);
+       medge_new =             result->getEdgeArray(result);
+       
+       origindex= result->getFaceDataArray(result, CD_ORIGINDEX);
+       
+       /* Set the locations of the first set of verts */
+       
+       mv_new= mvert_new;
+       mv_orig= mvert_orig;
+       
+       /* Copy the first set of edges */
+       med_orig= medge_orig;
+       med_new= medge_new;
+       for (i=0; i < totedge; i++, med_orig++, med_new++) {
+               med_new->v1= med_orig->v1;
+               med_new->v2= med_orig->v2;
+               med_new->crease= med_orig->crease;
+               med_new->flag= med_orig->flag &  ~ME_LOOSEEDGE;
+       }
+       
+       if(ltmd->flag & MOD_SCREW_NORMAL_CALC) {
+               /*
+                * Normal Calculation (for face flipping)
+                * Sort edge verts for correct face flipping
+                * NOT REALLY NEEDED but face flipping is nice.
+                *
+                * */
+
+
+               /* Notice!
+                *
+                * Since we are only ordering the edges here it can avoid 
mallocing the
+                * extra space by abusing the vert array berfore its filled 
with new verts.
+                * The new array for vert_connect must be at least 
sizeof(ScrewVertConnect) * totvert
+                * and the size of our resulting meshes array is sizeof(MVert) 
* totvert * 3
+                * so its safe to use the second 2 thrids of MVert the array 
for vert_connect,
+                * just make sure ScrewVertConnect struct is no more then twice 
as big as MVert,
+                * at the moment there is no chance of that being a problem,
+                * unless MVert becomes half its current size.
+                *
+                * once the edges are ordered, vert_connect is not needed and 
it can be used for verts
+                *
+                * This makes the modifier faster with one less alloc.
+                */
+
+               vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, 
"ScrewVertConnect");
+               //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* 
skip the first slice of verts */
+               vc= vert_connect;
+
+               /* Copy Vert Locations */
+               /* - We can do this in a later loop - only do here if no normal 
calc */
+               if (!totedge) {
+                       for (i=0; i < totvert; i++, mv_orig++, mv_new++) {
+                               copy_v3_v3(mv_new->co, mv_orig->co);
+                               normalize_v3_v3(vc->no, mv_new->co); /* no 
edges- this is realy a dummy normal */
+                       }
+               } else {
+                       /*printf("\n\n\n\n\nStarting Modifier\n");*/
+                       /* set edge users */
+                       med_new= medge_new;

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to