Index: source/blender/blenkernel/intern/modifier.c =================================================================== --- source/blender/blenkernel/intern/modifier.c (revision 10877) +++ source/blender/blenkernel/intern/modifier.c (working copy) @@ -552,6 +552,439 @@ return result; } +/* Slice */ +/* Slice */ +typedef struct SliceEdge { + /* ...we store them here so we can make a new vert intbetween their locations + * These 2 values are the indicies of the 2 verts on the original derived mesh... */ + int v1, v2; + + /* the index for the vert this edge will create + * once we know the total vert count and allocate the verts */ + struct SliceEdge *se_sib_a, *se_sib_b; + + /* also store the 2 new vert indicies */ + EditVert *eve; +} SliceEdge; + +static void sliceModifier_initData(ModifierData *md) +{ + SliceModifierData *smd = (SliceModifierData*) md; + + smd->gap = 0.25; + smd->gap_offset = 0.5; + smd->dir_ob = NULL; + smd->axis = 2; /* Z axis */ + smd->flag= 0; +} + +static void sliceModifier_copyData(ModifierData *md, ModifierData *target) +{ + SliceModifierData *smd = (SliceModifierData*) md; + SliceModifierData *tsmd = (SliceModifierData*) target; + + tsmd->gap = smd->gap; + tsmd->gap_offset = smd->gap_offset; + tsmd->dir_ob = smd->dir_ob; + tsmd->axis = smd->axis; + tsmd->flag = smd->flag; +} + +static void sliceModifier_foreachObjectLink( + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) +{ + SliceModifierData *smd = (SliceModifierData*) md; + + walk(userData, ob, &smd->dir_ob); +} + +static int sliceModifier_dependsOnTime(ModifierData *md) +{ + return 0; +} + +/* What edges of the face cross the line? */ +static DerivedMesh *sliceModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + DerivedMesh *dm = derivedData; + DerivedMesh *result=NULL; + SliceModifierData *smd = (SliceModifierData*) md; + int i, j, ok; + int maxVerts=0, maxFaces=0, maxEdges=0; + int totvert, totedge, totface; + char some_error= 0; + float (*coords)[3], co[3]; + float vmin, vmax; + float f1,f2,f3,f4, slice_level; /* face z levels */ + 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], mtx_tmp_b[4][4]; + + float w1, w2, wtot; + + MFace *mface, *mf; + MEdge *medge, *med; + MVert *mvert, *mv; + + EditFace *efa; + EditFace *eed; + EditVert *eve; + + int ev1,ev2,ev3,ev4; + int slice_edges_count = 0, slice_edges_done_count; + + SliceEdge *slice_edge_array; + /* each face can have 2 edges that intersect the slice_level + when looping through the faces, assign a slice edge for each */ + SliceEdge *slice_edge_1, *slice_edge_2; + SliceEdge *slice_edge; /* general use */ + + ListBase edit_verts; + ListBase edit_edges; + ListBase edit_faces; + + + edit_verts.first= edit_verts.last= + edit_edges.first= edit_edges.last= + edit_faces.first= edit_faces.last= NULL; + + totvert = dm->getNumVerts(dm); + totedge = dm->getNumEdges(dm); + totface = dm->getNumFaces(dm); + + if (totface < 3) { + result= CDDM_from_template(dm, 0, 0, 0); + return result; + } + + /* These are the transformed coords that we use to testing the Z level of the verts */ + coords = MEM_mallocN(sizeof(*coords) * totvert, "uvprojectModifier_do coords"); + dm->getVertCos(dm, coords); + mface = dm->getFaceArray(dm); + + + /* convert coords to world space */ + if (smd->dir_ob) { + Mat4Invert(mtx_tmp_a, ob->obmat); + Mat4CpyMat4(mtx_tx_inv, smd->dir_ob->obmat); + Mat4MulMat4(mtx_tmp_b, mtx_tx_inv, mtx_tmp_a); + Mat4CpyMat4(mtx_tx_inv, mtx_tmp_b); + Mat4Invert(mtx_tx, mtx_tx_inv); + + for(i=0; i < totvert; i++) { + Mat4MulVecfl(mtx_tx, coords[i]); + if (smd->axis==0) { + SWAP(float, coords[i][0], coords[i][2]); + } else if (smd->axis==1) { + SWAP(float, coords[i][1], coords[i][2]); + } + + if (i==0) { + vmin= vmax = coords[i][2]; + } else { + vmin = MIN2(vmin, coords[i][2]); + vmax = MAX2(vmax, coords[i][2]); + } + } + } else { + vmin= vmax = coords[0][2]; + for(i=0; i < totvert; i++) { + if (smd->axis==0) { + SWAP(float, coords[i][0], coords[i][2]); + } else if (smd->axis==1) { + SWAP(float, coords[i][1], coords[i][2]); + } + vmin = MIN2(vmin, coords[i][2]); + vmax = MAX2(vmax, coords[i][2]); + } + } + + slice_edge_array = MEM_mallocN(sizeof(SliceEdge) * totedge, "sliceEdges"); + + slice_level = (floor(vmin/smd->gap)*smd->gap)-smd->gap_offset; + /* will never loop more then a few times */ + while (slice_level < vmin) slice_level += smd->gap; + + for (; slice_level < vmax; slice_level+=smd->gap) { + EdgeHash *edge_hash = BLI_edgehash_new(); + mf= mface; + slice_edges_count= -1; + slice_edges_done_count = 0; + ok=1; + + for(i = 0; i < totface; i++, mf++) { + /* for less annpyoing access */ + f1= coords[mf->v1][2]; + f2= coords[mf->v2][2]; + f3= coords[mf->v3][2]; + if (mf->v4) f4= coords[mf->v4][2]; + + ev1=ev2=ev3=ev4=-1; + + /* This block of if's checks the face for intersetcing + * the cut line */ + if ((f1<=slice_level) != (f2<=slice_level)) { + ev1=mf->v1; ev2=mf->v2; + } if ((f2<=slice_level) != (f3<=slice_level)) { + if (ev1==-1) { + ev1=mf->v2; ev2=mf->v3; + } else { + ev3=mf->v2; ev4=mf->v3; + } + } if (mf->v4) { + if ((f3<=slice_level) != (f4<=slice_level)) { + if (ev1==-1) { + ev1=mf->v3; ev2=mf->v4; + } else { + ev3=mf->v3; ev4=mf->v4; + } + } if ((f4<=slice_level) != (f1<=slice_level)) { + if (ev1==-1) { + ev1=mf->v4; ev2=mf->v1; + } else { + ev3=mf->v4; ev4=mf->v1; + } + } + } else { + if ((f3<=slice_level) != (f1<=slice_level)) { + if (ev1==-1) { + ev1=mf->v3; ev2=mf->v1; + } else { + ev3=mf->v3; ev4=mf->v1; + } + } + } + + if (ev3!=-1) { + /* We have an intersecting face */ + slice_edge_1 = (SliceEdge *)BLI_edgehash_lookup(edge_hash, ev1, ev2); + slice_edge_2 = (SliceEdge *)BLI_edgehash_lookup(edge_hash, ev3, ev4); + + if (!slice_edge_1) { + slice_edge_1 = &slice_edge_array[++slice_edges_count]; + + BLI_edgehash_insert(edge_hash, ev1, ev2, slice_edge_1); + slice_edge_1->v1 = ev1; + slice_edge_1->v2 = ev2; + + slice_edge_1->se_sib_a= NULL; + slice_edge_1->se_sib_b= NULL; + + w1 = fabs(coords[ev1][2]-slice_level); + w2 = fabs(coords[ev2][2]-slice_level); + wtot = w1+w2; w1=w1/wtot; w2=w2/wtot; + co[0] = (coords[ev1][0]*w2) + (coords[ev2][0]*w1); + co[1] = (coords[ev1][1]*w2) + (coords[ev2][1]*w1); + co[2] = slice_level; + slice_edge_1->eve = BLI_addfillvert(co); + slice_edge_1->eve->tmp.l = mf->mat_nr; + maxVerts++; + } + + if (!slice_edge_2) { + slice_edge_2 = &slice_edge_array[++slice_edges_count]; + BLI_edgehash_insert(edge_hash, ev3, ev4, slice_edge_2); + slice_edge_2->v1 = ev3; + slice_edge_2->v2 = ev4; + + slice_edge_2->se_sib_a= NULL; + slice_edge_2->se_sib_b= NULL; + + w1 = fabs(coords[ev3][2]-slice_level); + w2 = fabs(coords[ev4][2]-slice_level); + wtot = w1+w2; w1=w1/wtot; w2=w2/wtot; + co[0] = (coords[ev3][0]*w2) + (coords[ev4][0]*w1); + co[1] = (coords[ev3][1]*w2) + (coords[ev4][1]*w1); + co[2] = slice_level; + slice_edge_2->eve = BLI_addfillvert(co); + slice_edge_2->eve->tmp.l = mf->mat_nr; + maxVerts++; + } + + if (!slice_edge_1->se_sib_a) { + slice_edge_1->se_sib_a = slice_edge_2; + } else if (!slice_edge_1->se_sib_b) { + slice_edge_1->se_sib_b = slice_edge_2; + slice_edges_done_count++; /* mark that we'v finished this edge */ + } else { + ok = 0; /* 3 faces use this edge? - dont fill at all */ + break; + } + + if (!slice_edge_2->se_sib_a) { + slice_edge_2->se_sib_a = slice_edge_1; + } else if (!slice_edge_2->se_sib_b) { + slice_edge_2->se_sib_b = slice_edge_1; + slice_edges_done_count++; /* mark that we'v finished this edge */ + } else { + ok = 0; /* 3 faces use this edge? - dont fill at all */ + break; + } + } + } + + BLI_edgehash_free(edge_hash, NULL); + + if ((slice_edges_count>=2) && (slice_edges_count+1 == slice_edges_done_count) && ok) { + + /* Adding Fill edges */ + for (j=0, slice_edge=slice_edge_array; j<=slice_edges_count; j++, slice_edge++) { + if (slice_edge->se_sib_a) { + BLI_addfilledge(slice_edge->eve, slice_edge->se_sib_a->eve); + if (slice_edge->se_sib_a->se_sib_a==slice_edge) + slice_edge->se_sib_a->se_sib_a= NULL; + else if (slice_edge->se_sib_a->se_sib_b==slice_edge) + slice_edge->se_sib_a->se_sib_b= NULL; + slice_edge->se_sib_a = NULL; + } + + if (slice_edge->se_sib_b) { + BLI_addfilledge(slice_edge->eve, slice_edge->se_sib_b->eve); + if (slice_edge->se_sib_b->se_sib_a==slice_edge) + slice_edge->se_sib_b->se_sib_a= NULL; + else if (slice_edge->se_sib_b->se_sib_b==slice_edge) + slice_edge->se_sib_b->se_sib_b= NULL; + slice_edge->se_sib_b = NULL; + } + } + + if (smd->flag & (MOD_SLICE_FLAG_NOFACE)) { + addlisttolist(&edit_edges, &filledgebase); + } else { + BLI_edgefill(0, 0); /* assign materials later */ + maxEdges = BLI_countlist(&filledgebase); + addlisttolist(&edit_faces, &fillfacebase); + } + + addlisttolist(&edit_verts, &fillvertbase); + fillvertbase.first= fillvertbase.last= + filledgebase.first= filledgebase.last= + fillfacebase.first= fillfacebase.last= NULL; + } + } + + if (smd->flag & (MOD_SLICE_FLAG_NOFACE)) { + maxEdges = BLI_countlist(&edit_edges); + + if (maxEdges) { + result = CDDM_from_template(dm, maxVerts, maxEdges, 0); + medge = CDDM_get_edges(result); + } + + } else { + maxFaces = BLI_countlist(&edit_faces); + + if (some_error) + modifier_setError(md, "Non manifold edge found."); + + if (maxFaces) { + result = CDDM_from_template(dm, maxVerts, 0, maxFaces); + mface = CDDM_get_faces(result); + } + } + + if (!result) { + /* no data */ + result = CDDM_from_template(dm, 0, 0, 0); + } else { + /* we know maxFaces or maxEdges is > 1 */ + mvert = CDDM_get_verts(result); + + /* Creating Mesh - set vert locatations, do this for edges and faces */ + for (eve = edit_verts.first, mv=mvert, i=0; eve; eve= eve->next, i++, mv++){ + /*Copying and indexing vert*/ + eve->keyindex= i; + VECCOPY(mv->co, eve->co); + + /* support slizing on different axis */ + if (smd->axis==0) { + SWAP(float, mv->co[0], mv->co[2]); + } else if (smd->axis==1) { + SWAP(float, mv->co[1], mv->co[2]); + } + + if (smd->dir_ob) + Mat4MulVecfl(mtx_tx_inv, mv->co); + } + + + if (smd->flag & (MOD_SLICE_FLAG_NOFACE)) { + med = medge; + for (eed = edit_edges.first; eed; eed= eed->next, med++){ + med->v1= eed->v1->keyindex; + med->v2= eed->v2->keyindex; + med->flag = ME_EDGEDRAW; + } + } else { + /* Creating Faces */ + mf = mface; + for (efa = edit_faces.first; efa; efa= efa->next, mf++){ + if (smd->flag & MOD_SLICE_FLAG_FLIP) { + if (efa->v1->keyindex==0) { + mf->v3= efa->v2->keyindex; + mf->v2= efa->v3->keyindex; + mf->v1= efa->v1->keyindex; + } else { + mf->v3= efa->v1->keyindex; + mf->v2= efa->v2->keyindex; + mf->v1= efa->v3->keyindex; + } + } else { + if (efa->v3->keyindex==0) { + mf->v1= efa->v3->keyindex; + mf->v2= efa->v1->keyindex; + mf->v3= efa->v2->keyindex; + } else { + mf->v1= efa->v1->keyindex; + mf->v2= efa->v2->keyindex; + mf->v3= efa->v3->keyindex; + } + } + mf->v4= 0; /* we know they are all Tri's */ + + /* get the material from this vert, an approximation + * but there is no good solution for this problem, + * The face made between 2 edges has no correct material. + * This at least will correctly work when different discreet + * elements have their materials set */ + mf->mat_nr = efa->v1->tmp.l; + } + CDDM_calc_edges(result); + } + } + BLI_end_edgefill(); + MEM_freeN(coords); + MEM_freeN(slice_edge_array); + + return result; +} + +static void sliceModifier_updateDepgraph( + ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) +{ + SliceModifierData *smd = (SliceModifierData*) md; + + if(smd->dir_ob) { + DagNode *curNode = dag_get_node(forest, smd->dir_ob); + + dag_add_relation(forest, curNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA); + } +} + +/* This dosnt work with material*/ +static DerivedMesh *sliceModifier_applyModifierEM( + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) +{ + return sliceModifier_applyModifier(md, ob, derivedData, 0, 1); +} + /* Array */ /* Array modifier: duplicates the object multiple times along an axis */ @@ -4942,6 +5375,19 @@ mti->dependsOnTime = buildModifier_dependsOnTime; mti->applyModifier = buildModifier_applyModifier; + mti = INIT_TYPE(Slice); + mti->type = eModifierTypeType_Constructive; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode; + mti->initData = sliceModifier_initData; + mti->copyData = sliceModifier_copyData; + mti->foreachObjectLink = sliceModifier_foreachObjectLink; + mti->updateDepgraph = sliceModifier_updateDepgraph; + mti->dependsOnTime = sliceModifier_dependsOnTime; + mti->applyModifier = sliceModifier_applyModifier; + mti->applyModifierEM = sliceModifier_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 10877) +++ source/blender/makesdna/DNA_modifier_types.h (working copy) @@ -28,6 +28,7 @@ eModifierType_UVProject, eModifierType_Smooth, eModifierType_Cast, + eModifierType_Slice, NUM_MODIFIER_TYPES } ModifierType; @@ -95,6 +96,20 @@ int randomize, seed; } BuildModifierData; +typedef struct SliceModifierData { + ModifierData modifier; + struct Object *dir_ob; + float gap; + float gap_offset; + short axis; + char pad[6]; + short flag; + char pad1[6]; +} SliceModifierData; +/* SliceModifierData->flag */ +#define MOD_SLICE_FLAG_FLIP 1 +#define MOD_SLICE_FLAG_NOFACE 2 + typedef struct ArrayModifierData { ModifierData modifier; Index: source/blender/src/buttons_editing.c =================================================================== --- source/blender/src/buttons_editing.c (revision 10877) +++ source/blender/src/buttons_editing.c (working copy) @@ -1563,6 +1563,8 @@ height = 72; } else if (md->type==eModifierType_Build) { height = 86; + } else if (md->type==eModifierType_Slice) { + height = 105; } else if (md->type==eModifierType_Mirror) { height = 67; } else if (md->type==eModifierType_EdgeSplit) { @@ -1666,6 +1668,25 @@ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:", lx, (cy-=19), buttonWidth,19, &bmd->length, 1.0, MAXFRAMEF, 100, 0, "Specify the total time the build effect requires"); uiDefButI(block, TOG, B_MODIFIER_RECALC, "Randomize", lx, (cy-=19), buttonWidth,19, &bmd->randomize, 0, 0, 1, 0, "Randomize the faces or edges during build."); uiDefButI(block, NUM, B_MODIFIER_RECALC, "Seed:", lx, (cy-=19), buttonWidth,19, &bmd->seed, 1.0, MAXFRAMEF, 100, 0, "Specify the seed for random if used."); + } else if (md->type==eModifierType_Slice) { + SliceModifierData *smd = (SliceModifierData*) md; + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_MODIFIER_RECALC, "Slice Gap:", lx, (cy-=19), buttonWidth,19, &smd->gap, 0.001, 10.0, 10, 10, "Gap between each slice"); + + uiDefButS(block, ROW,B_MODIFIER_RECALC,"X", lx, (cy-=19), buttonWidth/3,19, &smd->axis, 12.0, 0, 0, 0, "The axis that the slices face"); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"Y", (lx+buttonWidth/3), cy, buttonWidth/3,19, &smd->axis, 12.0, 1, 0, 0, "The axis that the slices face"); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"Z", (lx+2*buttonWidth/3), cy, buttonWidth/3,19, &smd->axis, 12.0, 2, 0, 0, "The axis that the slices face"); + + uiDefButF(block, NUM, B_MODIFIER_RECALC, "Slice Offset:", lx, (cy-=19), buttonWidth,19, &smd->gap_offset, 0.0, 1.0, 10, 10, "Offset of the slice"); + but = uiDefIDPoinBut(block, test_obpoin_but, ID_OB, + B_CHANGEDEP, "Ob: ", + lx,(cy-=19), buttonWidth, 19, + &smd->dir_ob, + "Control object: slice the axis of this object"); + + uiDefButBitS(block, TOG, MOD_SLICE_FLAG_FLIP, B_MODIFIER_RECALC, "Flip", lx, (cy-=19), buttonWidth/2,19, &smd->flag, 0, 0, 0, 0, "Flip the resulting faces"); + uiDefButBitS(block, TOG, MOD_SLICE_FLAG_NOFACE, B_MODIFIER_RECALC, "Outline", (lx+buttonWidth/2), cy, buttonWidth/2,19, &smd->flag, 0, 0, 0, 0, ""); + uiBlockEndAlign(block); } else if (md->type==eModifierType_Mirror) { MirrorModifierData *mmd = (MirrorModifierData*) md; uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Limit:", lx, (cy-=19), buttonWidth,19, &mmd->tolerance, 0.0, 1.0, 10, 10, "Distance from axis within which mirrored vertices are merged"); Index: config/linux2-config.py =================================================================== --- config/linux2-config.py (revision 10877) +++ config/linux2-config.py (working copy) @@ -123,7 +123,7 @@ WITH_BF_STATICOPENGL = 'false' BF_OPENGL = '/usr' BF_OPENGL_INC = '${BF_OPENGL}/include' -BF_OPENGL_LIB = 'GL GLU X11 Xi' +BF_OPENGL_LIB = 'GL GLU Xi' BF_OPENGL_LIBPATH = '/usr/X11R6/lib' BF_OPENGL_LIB_STATIC = '${BF_OPENGL}/libGL.a ${BF_OPENGL}/libGLU.a ${BF_OPENGL}/libXxf86vm.a ${BF_OPENGL}/libX11.a ${BF_OPENGL}/libXi.a ${BF_OPENGL}/libXext.a ${BF_OPENGL}/libXxf86vm.a'