Index: source/blender/blenkernel/intern/modifier.c =================================================================== --- source/blender/blenkernel/intern/modifier.c (Revision 19010) +++ source/blender/blenkernel/intern/modifier.c (Arbeitskopie) @@ -116,6 +116,10 @@ /***/ +/* Since were using normals a bit */ +#define NORM_SHORT_TO_FLOAT(fln, shn) fln[0]=shn[0]/32767.0f; fln[1]=shn[1]/32767.0f; fln[2]=shn[2]/32767.0f; +#define NORM_FLOAT_TO_SHORT(shn, fln) shn[0]=(short)(fln[0]*32767.0f); shn[1]=(short)(fln[1]*32767.0f); shn[2]=(short)(fln[2]*32767.0f); + static int noneModifier_isDisabled(ModifierData *md) { return 1; @@ -944,6 +948,706 @@ return result; } +/* Lathe */ +/* Lathe modifier: revolves the edges about an axis +*/ + +/* used for gathering edge connectivity */ +typedef struct LatheVertConnect { + 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; +} LatheVertConnect; + +typedef struct LatheVertIter { + LatheVertConnect * v_array; + LatheVertConnect * v_poin; + int v; + int v_other; + MEdge *e; +} LatheVertIter; + +#define LatheVertIter_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;\ + } + +/* GCC Warns of incompatible pointers here + * but its only when setting the edge and vert to NULL + * on line "iter.e = iter.v_poin = NULL;" + */ +#define LatheVertIter_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 = iter.v_poin = NULL;\ + } + +static void latheModifier_initData(ModifierData *md) +{ + LatheModifierData *ltmd = (LatheModifierData*) md; + ltmd->ob_axis = NULL; + ltmd->deg = 360.0f; + ltmd->axis = 2; + ltmd->flag = 0; + ltmd->steps = 16; + ltmd->renderSteps = 16; +} + +static void latheModifier_copyData(ModifierData *md, ModifierData *target) +{ + LatheModifierData *sltmd = (LatheModifierData*) md; + LatheModifierData *tltmd = (LatheModifierData*) target; + + tltmd->ob_axis = sltmd->ob_axis; + tltmd->deg = sltmd->deg; + tltmd->axis = sltmd->axis; + tltmd->flag = sltmd->flag; + tltmd->steps = sltmd->steps; + tltmd->renderSteps = sltmd->renderSteps; +} + +static DerivedMesh *latheModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + DerivedMesh *dm = derivedData; + DerivedMesh *result; + LatheModifierData *ltmd = (LatheModifierData*) 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, 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; + + LatheVertConnect *vc, *vc_tmp, *vert_connect; + + + 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->renderSteps; + else + steps = ltmd->steps; + + /* will the lathe be closed? */ + if (fabs(ltmd->deg) + 0.000001 > 360.0) { + 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; + } 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); + } + + axis_vec[ltmd->axis] = 1.0; + if (ltmd->ob_axis) { + /* calc the matrix relative to the axis object */ + Mat4Invert(mtx_tmp_a, ob->obmat); + Mat4CpyMat4(mtx_tx_inv, ltmd->ob_axis->obmat); + Mat4MulMat4(mtx_tx, mtx_tx_inv, mtx_tmp_a); + + /* calc the axis vec */ + Mat4Mul3Vecfl(mtx_tx, axis_vec); + Normalize(axis_vec); + } else { + /* exis char is used by i_rotate*/ + if (ltmd->axis==0) axis_char= 'x'; + else if (ltmd->axis==1) axis_char= 'y'; + else axis_char= 'z'; + } + + 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; + } + + /* + * 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(LatheVertConnect) * 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 LatheVertConnect 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(LatheVertConnect) * totvert, "LatheVertConnect"); + //vert_connect = (LatheVertConnect *) &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++) { + VECCOPY(mv_new->co, mv_orig->co); + + VECCOPY(vc->no, mv_new->co); /* no edges- this is realy a dummy normal */ + Normalize(vc->no); + } + } else { + /*printf("\n\n\n\n\nStarting Modifier\n");*/ + /* set edge users */ + med_new= medge_new; + mv_new= mvert_new; + + 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; + } + + if (ltmd->ob_axis) { + /*mtx_tx is initialized early on */ + for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) { + vc->co[0] = mv_new->co[0] = mv_orig->co[0]; + vc->co[1] = mv_new->co[1] = mv_orig->co[1]; + vc->co[2] = mv_new->co[2] = mv_orig->co[2]; + + vc->flag= 0; + vc->e[0] = vc->e[1] = NULL; + vc->v[0] = vc->v[1] = -1; + + Mat4Mul3Vecfl(mtx_tx, vc->co); + /* length in 2d, dont sqrt because this is only for comparison */ + vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] + + vc->co[other_axis_2]*vc->co[other_axis_2]; + + /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ + } + } else { + for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) { + vc->co[0] = mv_new->co[0] = mv_orig->co[0]; + vc->co[1] = mv_new->co[1] = mv_orig->co[1]; + vc->co[2] = mv_new->co[2] = mv_orig->co[2]; + + vc->flag= 0; + vc->e[0] = vc->e[1] = NULL; + vc->v[0] = vc->v[1] = -1; + + /* length in 2d, dont sqrt because this is only for comparison */ + vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] + + vc->co[other_axis_2]*vc->co[other_axis_2]; + + /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ + } + } + + /* this loop builds connectivity info for verts */ + for (i=0; iv1]; + + if (vc->v[0]==-1) { /* unused */ + vc->v[0] = med_new->v2; + vc->e[0] = med_new; + } else if (vc->v[1]==-1) { + vc->v[1] = med_new->v2; + vc->e[1] = med_new; + } else { + vc->v[0] = vc->v[1] = -2; /* erro value - dont use, 3 edges on vert */ + } + + vc = &vert_connect[med_new->v2]; + + /* same as above but swap v1/2 */ + if (vc->v[0]==-1) { /* unused */ + vc->v[0] = med_new->v1; + vc->e[0] = med_new; + } else if (vc->v[1]==-1) { + vc->v[1] = med_new->v1; + vc->e[1] = med_new; + } else { + vc->v[0] = vc->v[1] = -2; /* erro value - dont use, 3 edges on vert */ + } + } + + /* find the first vert */ + vc = vert_connect; + for (i=0; i < totvert; i++, vc++) { + int VBEST=-1, ed_loop_closed=0; /* vert and vert new */ + int ed_loop_flip; + float fl = -1.0f; + LatheVertIter lt_iter; + + /* Now do search for connected verts, order all edges and flip them + * so resulting faces are flipped the right way */ + vc_tot_linked = 0; /* count the number of linked verts for this loop */ + if (vc->flag==0) { + /*printf("Loop on connected vert: %i\n", i);*/ + + for(j=0; j<2; j++) { + /*printf("\tSide: %i\n", j);*/ + LatheVertIter_INIT(lt_iter, vert_connect, i, j); + if (j==1) { + LatheVertIter_NEXT(lt_iter); + } + while (lt_iter.v_poin) { + /*printf("\t\tVERT: %i\n", lt_iter.v);*/ + if (lt_iter.v_poin->flag) { + /*printf("\t\t\tBreaking Found end\n");*/ + //endpoints[0] = endpoints[1] = -1; + ed_loop_closed = 1; /* circle */ + break; + } + lt_iter.v_poin->flag= 1; + vc_tot_linked++; + /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/ + if (fl <= lt_iter.v_poin->dist) { + fl = lt_iter.v_poin->dist; + VBEST = lt_iter.v; + /*printf("\t\t\tVERT BEST: %i\n", VBEST);*/ + } + LatheVertIter_NEXT(lt_iter); + if (!lt_iter.v_poin) { + /*printf("\t\t\tFound End Also Num %i\n", j);*/ + /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */ + break; + } + } + } + + /* now we have a collection of used edges. flip their edges the right way*/ + /*if (VBEST !=-1) - */ + + /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/ + + if (vc_tot_linked>1) { + float vf_1, vf_2, vf_best; + + vc_tmp = &vert_connect[VBEST]; + + tmpf1 = ((&vert_connect[vc_tmp->v[0]])->co); + tmpf2 = ((&vert_connect[vc_tmp->v[1]])->co); + + + /* edge connects on each side! */ + if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) { + /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/ + /* find out which is higher */ + + vf_1= tmpf1[ltmd->axis]; + vf_2= tmpf2[ltmd->axis]; + vf_best= vc_tmp->co[ltmd->axis]; + + if (vf_1 < vf_best && vf_best < vf_2) { + ed_loop_flip = 0; + } else if (vf_1 > vf_best && vf_best > vf_2) { + ed_loop_flip = 1; + } else { + /* not so simple to work out wich edge is higher */ + VECSUB(tmp_vec1, tmpf1, vc_tmp->co); + VECSUB(tmp_vec1, tmpf2, vc_tmp->co); + Normalize(tmp_vec1); + Normalize(tmp_vec2); + + if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) { + ed_loop_flip = 1; + } else { + ed_loop_flip = 0; + } + } + } else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */ + /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/ + if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */ + ed_loop_flip = 1; + } else { /* best is below or even... in even case we cant know whet to do. */ + ed_loop_flip = 0; + } + + }/* else { + printf("No Connected ___\n"); + }*/ + + /*printf("flip direction %i\n", ed_loop_flip);*/ + + + /* switch the flip option if set */ + if (ltmd->flag & MOD_LATHE_NORMAL_FLIP) { + if (ed_loop_flip) ed_loop_flip = 0; + else ed_loop_flip = 1; + } + if (ltmd->deg < 0.0f) { + if (ed_loop_flip) ed_loop_flip = 0; + else ed_loop_flip = 1; + } + + /* if its closed, we only need 1 loop */ + for(j=ed_loop_closed; j<2; j++) { + /*printf("Ordering Side J %i\n", j);*/ + + LatheVertIter_INIT(lt_iter, vert_connect, VBEST, j); + /*printf("\n\nStarting - Loop\n");*/ + lt_iter.v_poin->flag = 1; /* so a non loop will traverse the other side */ + + + /* If this is the vert off the best vert and + * the best vert has 2 edges connected too it + * then swap the flip direction */ + if (j==1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) { + if (ed_loop_flip) ed_loop_flip = 0; + else ed_loop_flip = 1; + } + + while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) { + /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/ + + lt_iter.v_poin->flag = 2; + if (lt_iter.e) { + if (lt_iter.v == lt_iter.e->v1) { + if (ed_loop_flip==0) { + /*printf("\t\t\tFlipping 0\n");*/ + SWAP( int, lt_iter.e->v1, lt_iter.e->v2 ); + }/* else { + printf("\t\t\tFlipping Not 0\n"); + }*/ + } else if (lt_iter.v == lt_iter.e->v2) { + if (ed_loop_flip==1) { + /*printf("\t\t\tFlipping 1\n");*/ + SWAP( int, lt_iter.e->v1, lt_iter.e->v2 ); + }/* else { + printf("\t\t\tFlipping Not 1\n"); + }*/ + }/* else { + printf("\t\tIncorrect edge topology"); + }*/ + }/* else { + printf("\t\tNo Edge at this point\n"); + }*/ + LatheVertIter_NEXT(lt_iter); + } + } + } + } + + /* *VERTEX NORMALS* + * we know the surrounding edges are ordered correctly now + * so its safe to create vertex normals. + * + * calculate vertex normals that can be propodated on lathing + * use edge connectivity work this out */ + if (vc->v[0]>=0) { + if (vc->v[1]>=0) { + /* 2 edges connedted */ + /* make 2 connecting vert locations relative to the middle vert */ + VECSUB(tmp_vec1, (&mvert_new[vc->v[0]])->co, (&mvert_new[i])->co); + VECSUB(tmp_vec2, (&mvert_new[vc->v[1]])->co, (&mvert_new[i])->co); + /* normalize so both edges have the same influence, no matter their length */ + Normalize(tmp_vec1); + Normalize(tmp_vec2); + + /* vc_no_tmp1 - this line is the average direction of both connecting edges + * + * Use the edge order to make the subtraction, flip the normal the right way + * edge should be there but check just in case... */ + if (vc->e && vc->e[0]->v1 == i) { + VECSUB(tmp_vec1, tmp_vec1, tmp_vec2); + } else { + VECSUB(tmp_vec1, tmp_vec2, tmp_vec1); + } + + } else { + /* only 1 edge connected - same as above except + * dont need to average edge direction */ + if (vc->e && vc->e[0]->v2 == i) { + VECSUB(tmp_vec1, (&mvert_new[i])->co, (&mvert_new[vc->v[0]])->co); + } else { + VECSUB(tmp_vec1, (&mvert_new[vc->v[0]])->co, (&mvert_new[i])->co); + } + } + + /* vc_no_tmp2 - is a line 90d from the pivot to the vec + * This is used so the resulting normal points directly away from the middle */ + Crossf(tmp_vec2, axis_vec, vc->co); + + /* edge average vector and right angle to the pivot make the normal */ + Crossf(vc->no, tmp_vec1, tmp_vec2); + + } else { + VECCOPY(vc->no, vc->co); + } + + /* we wont be looping on this data again so copy normals here */ + if (ltmd->deg < 0.0) + VecMulf(vc->no, -1.0f); + + Normalize(vc->no); + NORM_FLOAT_TO_SHORT((&mvert_new[i])->no, vc->no); + + /* Done with normals */ + } + } + /* done with edge connectivity based normal flipping */ + + + /* Add Faces */ + for (i=1; i < steps; i++) { + /* Rotation Matrix */ + if (close) angle = (ltmd->deg / steps) * i; + else angle = (ltmd->deg / (steps-1)) * i; + + if (ltmd->ob_axis) { + VecRotToMat3(axis_vec, angle * M_PI/180.0f, mat3); + Mat4CpyMat3(mat, mat3); + + } else { + Mat4One(mat); + i_rotate(angle, axis_char, mat); + } + + mv_orig= mvert_orig; + mv_new= &mvert_new[totvert*i]; /* advance to the next slice */ + + for (j=0; jno); + + /* set location */ + VECCOPY(mv_new->co, mv_orig->co); + + /* only need to set these if using non cleared memory */ + /*mv_new->mat_nr = mv_new->flag = 0;*/ + + if (ltmd->ob_axis) { + mv_new->co[0] -= mtx_tx[3][0]; + mv_new->co[1] -= mtx_tx[3][1]; + mv_new->co[2] -= mtx_tx[3][2]; + + Mat4MulVecfl(mat, mv_new->co); + Mat4MulVecfl(mat, tmp_vec1); + + mv_new->co[0] += mtx_tx[3][0]; + mv_new->co[1] += mtx_tx[3][1]; + mv_new->co[2] += mtx_tx[3][2]; + } else { + Mat4MulVecfl(mat, mv_new->co); + Mat4MulVecfl(mat, tmp_vec1); + } + + /* set the normal now its transformed */ + NORM_FLOAT_TO_SHORT(mv_new->no, tmp_vec1); + + /* add the new edge */ + med_new->v1 = j+(i*totvert); + med_new->v2 = med_new->v1 - totvert; + med_new->flag = ME_EDGEDRAW|ME_EDGERENDER; + med_new++; + } + } + + if (close) { + /* last loop of edges, previous loop dosnt account for the last set of edges */ + for (i=0; iv1 = i+((steps-1)*totvert); + med_new->v2 = i; + med_new->flag = ME_EDGEDRAW|ME_EDGERENDER; + med_new++; + } + } + + mf_new = mface_new; + med_new_firstloop= medge_new; + + for (i=0; i < totedge; i++, med_new_firstloop++) { + /* for each edge, make a cylinder of quads */ + i1= med_new_firstloop->v1; + i2= med_new_firstloop->v2; + + for (j=0; j < steps-1; j++) { + + /* new face */ + mf_new->v1 = i1; + mf_new->v2 = i2; + mf_new->v3 = i2 + totvert; + mf_new->v4 = i1 + totvert; + + if( !mf_new->v3 || !mf_new->v4 ) { + SWAP( int, mf_new->v1, mf_new->v3 ); + SWAP( int, mf_new->v2, mf_new->v4 ); + } + mf_new->flag = ME_SMOOTH; + origindex[mface_index] = ORIGINDEX_NONE; + mf_new++; + mface_index++; + + /* new vertical edge */ + if (j) { /* The first set is alredw dome */ + med_new->v1 = i1; + med_new->v2 = i2; + med_new->flag = med_new_firstloop->flag; + med_new->crease = med_new_firstloop->crease; + med_new++; + } + i1 += totvert; + i2 += totvert; + } + + /* close the loop*/ + if (close) { + mf_new->v1 = i1; + mf_new->v2 = i2; + mf_new->v3 = med_new_firstloop->v2; + mf_new->v4 = med_new_firstloop->v1; + + if( !mf_new->v3 || !mf_new->v4 ) { + SWAP( int, mf_new->v1, mf_new->v3 ); + SWAP( int, mf_new->v2, mf_new->v4 ); + } + mf_new->flag = ME_SMOOTH; + origindex[mface_index] = ORIGINDEX_NONE; + mf_new++; + mface_index++; + } + + /* new vertical edge */ + med_new->v1 = i1; + med_new->v2 = i2; + med_new->flag = med_new_firstloop->flag & ~ME_LOOSEEDGE; + med_new->crease = med_new_firstloop->crease; + med_new++; + } + + /* we can avoid if using vert alloc trick */ + MEM_freeN(vert_connect); + + return result; +} + + +static void latheModifier_updateDepgraph( + ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) +{ + LatheModifierData *ltmd = (LatheModifierData*) md; + + if(ltmd->ob_axis) { + DagNode *curNode = dag_get_node(forest, ltmd->ob_axis); + + dag_add_relation(forest, curNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, + "Lathe Modifier"); + } +} + +static void latheModifier_foreachObjectLink( + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) +{ + LatheModifierData *ltmd = (LatheModifierData*) md; + + walk(userData, ob, <md->ob_axis); +} + +/* This dosnt work with material*/ +static DerivedMesh *latheModifier_applyModifierEM( + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) +{ + return latheModifier_applyModifier(md, ob, derivedData, 0, 1); +} + +static int latheModifier_dependsOnTime(ModifierData *md) +{ + return 0; +} + /* Array */ /* Array modifier: duplicates the object multiple times along an axis */ @@ -8049,6 +8753,20 @@ mti->updateDepgraph = maskModifier_updateDepgraph; mti->applyModifier = maskModifier_applyModifier; + mti = INIT_TYPE(Lathe); + mti->type = eModifierTypeType_Constructive; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; + + mti->initData = latheModifier_initData; + mti->copyData = latheModifier_copyData; + mti->foreachObjectLink = latheModifier_foreachObjectLink; + mti->dependsOnTime = latheModifier_dependsOnTime; + mti->updateDepgraph = latheModifier_updateDepgraph; + mti->applyModifier = latheModifier_applyModifier; + mti->applyModifierEM = latheModifier_applyModifierEM; + mti = INIT_TYPE(Array); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh Index: source/blender/makesdna/DNA_modifier_types.h =================================================================== --- source/blender/makesdna/DNA_modifier_types.h (Revision 19010) +++ source/blender/makesdna/DNA_modifier_types.h (Arbeitskopie) @@ -39,6 +39,7 @@ eModifierType_Fluidsim, eModifierType_Mask, eModifierType_SimpleDeform, + eModifierType_Lathe, NUM_MODIFIER_TYPES } ModifierType; @@ -125,6 +126,17 @@ /* Mask Modifier -> flag */ #define MOD_MASK_INV (1<<0) +typedef struct LatheModifierData { + ModifierData modifier; + struct Object *ob_axis; + int steps; + int renderSteps; + float deg; + short axis; + short flag; +} LatheModifierData; +#define MOD_LATHE_NORMAL_FLIP 1 + typedef struct ArrayModifierData { ModifierData modifier; Index: source/blender/src/buttons_editing.c =================================================================== --- source/blender/src/buttons_editing.c (Revision 19010) +++ source/blender/src/buttons_editing.c (Arbeitskopie) @@ -1888,6 +1888,8 @@ height = 31; } else if (md->type==eModifierType_Boolean) { height = 48; + } else if (md->type==eModifierType_Lathe) { + height = 105; } else if (md->type==eModifierType_Array) { height = 211; } else if (md->type==eModifierType_MeshDeform) { @@ -2375,6 +2377,27 @@ BooleanModifierData *bmd = (BooleanModifierData*) md; uiDefButI(block, MENU, B_MODIFIER_RECALC, "Operation%t|Intersect%x0|Union%x1|Difference%x2", lx,(cy-=19),buttonWidth,19, &bmd->operation, 0.0, 1.0, 0, 0, "Boolean operation to perform"); uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation"); + } else if (md->type==eModifierType_Lathe) { + LatheModifierData *ltmd = (LatheModifierData*) md; + uiBlockBeginAlign(block); + uiDefButI(block, NUM, B_MODIFIER_RECALC, "Steps:", lx, (cy-=19), buttonWidth,19, <md->steps, 3, 1024, 100, 0, "Lathe steps."); + uiDefButI(block, NUM, B_MODIFIER_RECALC, "Render Steps:", lx, (cy-=19), buttonWidth,19, <md->renderSteps, 3, 1024, 100, 0, "Lathe steps when rendering."); + uiDefButF(block, NUM, B_MODIFIER_RECALC, "Degr:", lx, (cy-=19), buttonWidth,19, <md->deg, -360.0, 360.0, 10, 10, ""); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"X", lx, (cy-=19), buttonWidth/6,19, <md->axis, 12.0, 0, 0, 0, "The axis that the slices face"); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"Y", (lx+buttonWidth/6), cy, buttonWidth/6,19, <md->axis, 12.0, 1, 0, 0, "The axis that the slices face"); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"Z", (lx+2*buttonWidth/6), cy, buttonWidth/6,19, <md->axis, 12.0, 2, 0, 0, "The axis that the slices face"); + uiBlockEndAlign(block); + + uiDefButBitS(block, TOG, MOD_LATHE_NORMAL_FLIP, B_MODIFIER_RECALC, "Flip Faces", (lx+buttonWidth/2),cy,buttonWidth/2,19, <md->flag, 0, 0, 0, 0, "Enable X axis mirror"); + + but = uiDefIDPoinBut(block, test_obpoin_but, ID_OB, + B_CHANGEDEP, "Ob: ", + lx,(cy-=19), buttonWidth, 19, + <md->ob_axis, + "Control object: slice the axis of this object"); } else if (md->type==eModifierType_Array) { ArrayModifierData *amd = (ArrayModifierData*) md; float range = 10000;