Fix for [#26133] Explode modifier doesn't care about UVs (Option "split edges")
authorJanne Karhu <jhkarh@gmail.com>
Wed, 23 Feb 2011 19:29:59 +0000 (19:29 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Wed, 23 Feb 2011 19:29:59 +0000 (19:29 +0000)
* This is basically a total rewrite of the edge split algorithm. The old one didn't handle tris at all and quads were cut wrong in some cases too with the addition of not handling uv coordinates at all.
* This new algorithm uses a flag system to categorize different splits and the identical but rotated cases in a similar way to how marching cubes indexes different cases.
* It cuts quads and tris and creates proper uv's for the new faces too.
* I also renamed the option to "edge cut" to differentiate if from the edge split modifier and added an option to override a uv-channel in the exploded mesh with particle age as x-coordinate so that the shrapnel can be faded out nicely etc.

release/scripts/ui/properties_data_modifier.py
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/intern/rna_modifier.c
source/blender/modifiers/intern/MOD_explode.c

index ecee6d0..003f4a2 100644 (file)
@@ -259,9 +259,11 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
         sub = col.column()
         sub.active = bool(md.vertex_group)
         sub.prop(md, "protect")
+        col.label(text="Particle UV")
+        col.prop_search(md, "particle_uv", ob.data, "uv_textures", text="")
 
         col = split.column()
-        col.prop(md, "use_edge_split")
+        col.prop(md, "use_edge_cut")
         col.prop(md, "show_unborn")
         col.prop(md, "show_alive")
         col.prop(md, "show_dead")
index 687a05f..28840d5 100644 (file)
@@ -588,7 +588,7 @@ typedef struct ParticleInstanceModifierData {
 typedef enum {
        eExplodeFlag_CalcFaces =        (1<<0),
        eExplodeFlag_PaSize =           (1<<1),
-       eExplodeFlag_EdgeSplit =        (1<<2),
+       eExplodeFlag_EdgeCut =          (1<<2),
        eExplodeFlag_Unborn =           (1<<3),
        eExplodeFlag_Alive =            (1<<4),
        eExplodeFlag_Dead =                     (1<<5),
@@ -599,6 +599,7 @@ typedef struct ExplodeModifierData {
        int *facepa;
        short flag, vgroup;
        float protect;
+       char uvname[32];
 } ExplodeModifierData;
 
 typedef struct MultiresModifierData {
index 07db55e..3c77ab6 100644 (file)
@@ -1720,9 +1720,9 @@ static void rna_def_modifier_explode(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Protect", "Clean vertex group edges");
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
-       prop= RNA_def_property(srna, "use_edge_split", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", eExplodeFlag_EdgeSplit);
-       RNA_def_property_ui_text(prop, "Split Edges", "Split face edges for nicer shrapnel");
+       prop= RNA_def_property(srna, "use_edge_cut", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", eExplodeFlag_EdgeCut);
+       RNA_def_property_ui_text(prop, "Cut Edges", "Cut face edges for nicer shrapnel");
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
        prop= RNA_def_property(srna, "show_unborn", PROP_BOOLEAN, PROP_NONE);
@@ -1744,6 +1744,12 @@ static void rna_def_modifier_explode(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flag", eExplodeFlag_PaSize);
        RNA_def_property_ui_text(prop, "Size", "Use particle size for the shrapnel");
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+       prop= RNA_def_property(srna, "particle_uv", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "uvname");
+       RNA_def_property_string_maxlength(prop, 32);
+       RNA_def_property_ui_text(prop, "Particle UV", "UV Layer to change with particle age");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
 }
 
 static void rna_def_modifier_cloth(BlenderRNA *brna)
index 67476a3..a0a6580 100644 (file)
@@ -180,15 +180,370 @@ static void createFacepa(ExplodeModifierData *emd,
        BLI_kdtree_free(tree);
 }
 
-static int edgesplit_get(EdgeHash *edgehash, int v1, int v2)
+static int edgecut_get(EdgeHash *edgehash, int v1, int v2)
 {
        return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2));
 }
 
-static DerivedMesh * splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
+const short add_faces[24] = {
+       0,
+       0, 0, 2, 0, 1, 2, 2, 0, 2, 1,
+       2, 2, 2, 2, 3, 0, 0, 0, 1, 0,
+       1, 1, 2
+ };
+
+MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFace *mf)
+{
+       MFace *df = CDDM_get_face(split, cur);
+       DM_copy_face_data(dm, split, i, cur, 1);
+       *df = *mf;
+       return df;
+}
+
+#define SET_VERTS(a, b, c, d) \
+                       v[0]=mf->v##a; uv[0]=a-1; \
+                       v[1]=mf->v##b; uv[1]=b-1; \
+                       v[2]=mf->v##c; uv[2]=c-1; \
+                       v[3]=mf->v##d; uv[3]=d-1;
+
+#define GET_ES(v1, v2) edgecut_get(eh, v1, v2);
+#define INT_UV(uvf, c0, c1) interp_v2_v2v2(uvf, mf->uv[c0], mf->uv[c1], 0.5f);
+
+static void remap_faces_3_6_9_12(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
+{
+       MFace *df1 = get_dface(dm, split, cur, i, mf);
+       MFace *df2 = get_dface(dm, split, cur+1, i, mf);
+       MFace *df3 = get_dface(dm, split, cur+2, i, mf);
+
+       facepa[cur] = vertpa[v1];
+       df1->v1 = v1;
+       df1->v2 = GET_ES(v1, v2)
+       df1->v3 = GET_ES(v2, v3)
+       df1->v4 = v3;
+       df1->flag |= ME_FACE_SEL;
+
+       facepa[cur+1] = vertpa[v2];
+       df2->v1 = GET_ES(v1, v2)
+       df2->v2 = v2;
+       df2->v3 = GET_ES(v2, v3)
+       df2->v4 = 0;
+       df2->flag &= ~ME_FACE_SEL;
+
+       facepa[cur+2] = vertpa[v1];
+       df3->v1 = v1;
+       df3->v2 = v3;
+       df3->v3 = v4;
+       df3->v4 = 0;
+       df3->flag &= ~ME_FACE_SEL;
+}
+
+static void remap_uvs_3_6_9_12(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+{
+       MTFace *mf, *df1, *df2, *df3;
+       int l;
+
+       for(l=0; l<numlayer; l++) {
+               mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+               df1 = mf+cur;
+               df2 = df1 + 1;
+               df3 = df1 + 2;
+               mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+               mf += i;
+
+               copy_v2_v2(df1->uv[0], mf->uv[c0]);
+               INT_UV(df1->uv[1], c0, c1)
+               INT_UV(df1->uv[2], c1, c2)
+               copy_v2_v2(df1->uv[3], mf->uv[c2]);
+
+               INT_UV(df2->uv[0], c0, c1)
+               copy_v2_v2(df2->uv[1], mf->uv[c1]);
+               INT_UV(df2->uv[2], c1, c2)
+
+               copy_v2_v2(df3->uv[0], mf->uv[c0]);
+               copy_v2_v2(df3->uv[1], mf->uv[c2]);
+               copy_v2_v2(df3->uv[2], mf->uv[c3]);
+       }
+}
+
+static void remap_faces_5_10(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
+{
+       MFace *df1 = get_dface(dm, split, cur, i, mf);
+       MFace *df2 = get_dface(dm, split, cur+1, i, mf);
+
+       facepa[cur] = vertpa[v1];
+       df1->v1 = v1;
+       df1->v2 = v2;
+       df1->v3 = GET_ES(v2, v3)
+       df1->v4 = GET_ES(v1, v4)
+       df1->flag |= ME_FACE_SEL;
+
+       facepa[cur+1] = vertpa[v3];
+       df2->v1 = GET_ES(v1, v4)
+       df2->v2 = GET_ES(v2, v3)
+       df2->v3 = v3;
+       df2->v4 = v4;
+       df2->flag |= ME_FACE_SEL;
+}
+
+static void remap_uvs_5_10(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+{
+       MTFace *mf, *df1, *df2;
+       int l;
+
+       for(l=0; l<numlayer; l++) {
+               mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+               df1 = mf+cur;
+               df2 = df1 + 1;
+               mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+               mf += i;
+
+               copy_v2_v2(df1->uv[0], mf->uv[c0]);
+               copy_v2_v2(df1->uv[1], mf->uv[c1]);
+               INT_UV(df1->uv[2], c1, c2)
+               INT_UV(df1->uv[3], c0, c3)
+
+               INT_UV(df2->uv[0], c0, c3)
+               INT_UV(df2->uv[1], c1, c2)
+               copy_v2_v2(df2->uv[2], mf->uv[c2]);
+               copy_v2_v2(df2->uv[3], mf->uv[c3]);
+
+       }
+}
+
+static void remap_faces_15(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
+{
+       MFace *df1 = get_dface(dm, split, cur, i, mf);
+       MFace *df2 = get_dface(dm, split, cur+1, i, mf);
+       MFace *df3 = get_dface(dm, split, cur+2, i, mf);
+       MFace *df4 = get_dface(dm, split, cur+3, i, mf);
+
+       facepa[cur] = vertpa[v1];
+       df1->v1 = v1;
+       df1->v2 = GET_ES(v1, v2)
+       df1->v3 = GET_ES(v1, v3)
+       df1->v4 = GET_ES(v1, v4)
+       df1->flag |= ME_FACE_SEL;
+
+       facepa[cur+1] = vertpa[v2];
+       df2->v1 = GET_ES(v1, v2)
+       df2->v2 = v2;
+       df2->v3 = GET_ES(v2, v3)
+       df2->v4 = GET_ES(v1, v3)
+       df2->flag |= ME_FACE_SEL;
+
+       facepa[cur+2] = vertpa[v3];
+       df3->v1 = GET_ES(v1, v3)
+       df3->v2 = GET_ES(v2, v3)
+       df3->v3 = v3;
+       df3->v4 = GET_ES(v3, v4)
+       df3->flag |= ME_FACE_SEL;
+
+       facepa[cur+3] = vertpa[v4];
+       df4->v1 = GET_ES(v1, v4)
+       df4->v2 = GET_ES(v1, v3)
+       df4->v3 = GET_ES(v3, v4)
+       df4->v4 = v4;
+       df4->flag |= ME_FACE_SEL;
+}
+
+static void remap_uvs_15(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+{
+       MTFace *mf, *df1, *df2, *df3, *df4;
+       int l;
+
+       for(l=0; l<numlayer; l++) {
+               mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+               df1 = mf+cur;
+               df2 = df1 + 1;
+               df3 = df1 + 2;
+               df4 = df1 + 3;
+               mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+               mf += i;
+
+               copy_v2_v2(df1->uv[0], mf->uv[c0]);
+               INT_UV(df1->uv[1], c0, c1)
+               INT_UV(df1->uv[2], c0, c2)
+               INT_UV(df1->uv[3], c0, c3)
+
+               INT_UV(df2->uv[0], c0, c1)
+               copy_v2_v2(df2->uv[1], mf->uv[c1]);
+               INT_UV(df2->uv[2], c1, c2)
+               INT_UV(df2->uv[3], c0, c2)
+
+               INT_UV(df3->uv[0], c0, c2)
+               INT_UV(df3->uv[1], c1, c2)
+               copy_v2_v2(df3->uv[2], mf->uv[c2]);
+               INT_UV(df3->uv[3], c2, c3)
+
+               INT_UV(df4->uv[0], c0, c3)
+               INT_UV(df4->uv[1], c0, c2)
+               INT_UV(df4->uv[2], c2, c3)
+               copy_v2_v2(df4->uv[3], mf->uv[c3]);
+       }
+}
+
+static void remap_faces_7_11_13_14(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
+{
+       MFace *df1 = get_dface(dm, split, cur, i, mf);
+       MFace *df2 = get_dface(dm, split, cur+1, i, mf);
+       MFace *df3 = get_dface(dm, split, cur+2, i, mf);
+
+       facepa[cur] = vertpa[v1];
+       df1->v1 = v1;
+       df1->v2 = GET_ES(v1, v2)
+       df1->v3 = GET_ES(v2, v3)
+       df1->v4 = GET_ES(v1, v4)
+       df1->flag |= ME_FACE_SEL;
+
+       facepa[cur+1] = vertpa[v2];
+       df2->v1 = GET_ES(v1, v2)
+       df2->v2 = v2;
+       df2->v3 = GET_ES(v2, v3)
+       df2->v4 = 0;
+       df2->flag &= ~ME_FACE_SEL;
+
+       facepa[cur+2] = vertpa[v4];
+       df3->v1 = GET_ES(v1, v4)
+       df3->v2 = GET_ES(v2, v3)
+       df3->v3 = v3;
+       df3->v4 = v4;
+       df3->flag |= ME_FACE_SEL;
+}
+
+static void remap_uvs_7_11_13_14(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+{
+       MTFace *mf, *df1, *df2, *df3;
+       int l;
+
+       for(l=0; l<numlayer; l++) {
+               mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+               df1 = mf+cur;
+               df2 = df1 + 1;
+               df3 = df1 + 2;
+               mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+               mf += i;
+
+               copy_v2_v2(df1->uv[0], mf->uv[c0]);
+               INT_UV(df1->uv[1], c0, c1)
+               INT_UV(df1->uv[2], c1, c2)
+               INT_UV(df1->uv[3], c0, c3)
+
+               INT_UV(df2->uv[0], c0, c1)
+               copy_v2_v2(df2->uv[1], mf->uv[c1]);
+               INT_UV(df2->uv[2], c1, c2)
+
+               INT_UV(df3->uv[0], c0, c3)
+               INT_UV(df3->uv[1], c1, c2)
+               copy_v2_v2(df3->uv[2], mf->uv[c2]);
+               copy_v2_v2(df3->uv[3], mf->uv[c3]);
+       }
+}
+
+static void remap_faces_19_21_22(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3)
+{
+       MFace *df1 = get_dface(dm, split, cur, i, mf);
+       MFace *df2 = get_dface(dm, split, cur+1, i, mf);
+
+       facepa[cur] = vertpa[v1];
+       df1->v1 = v1;
+       df1->v2 = GET_ES(v1, v2)
+       df1->v3 = GET_ES(v1, v3)
+       df1->v4 = 0;
+       df1->flag &= ~ME_FACE_SEL;
+
+       facepa[cur+1] = vertpa[v2];
+       df2->v1 = GET_ES(v1, v2)
+       df2->v2 = v2;
+       df2->v3 = v3;
+       df2->v4 = GET_ES(v1, v3)
+       df2->flag |= ME_FACE_SEL;
+}
+
+static void remap_uvs_19_21_22(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
+{
+       MTFace *mf, *df1, *df2;
+       int l;
+
+       for(l=0; l<numlayer; l++) {
+               mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+               df1 = mf+cur;
+               df2 = df1 + 1;
+               mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+               mf += i;
+
+               copy_v2_v2(df1->uv[0], mf->uv[c0]);
+               INT_UV(df1->uv[1], c0, c1)
+               INT_UV(df1->uv[2], c0, c2)
+
+               INT_UV(df2->uv[0], c0, c1)
+               copy_v2_v2(df2->uv[1], mf->uv[c1]);
+               copy_v2_v2(df2->uv[2], mf->uv[c2]);
+               INT_UV(df2->uv[3], c0, c2)
+       }
+}
+
+static void remap_faces_23(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3)
+{
+       MFace *df1 = get_dface(dm, split, cur, i, mf);
+       MFace *df2 = get_dface(dm, split, cur+1, i, mf);
+       MFace *df3 = get_dface(dm, split, cur+2, i, mf);
+
+       facepa[cur] = vertpa[v1];
+       df1->v1 = v1;
+       df1->v2 = GET_ES(v1, v2)
+       df1->v3 = GET_ES(v2, v3)
+       df1->v4 = GET_ES(v1, v3)
+       df1->flag |= ME_FACE_SEL;
+
+       facepa[cur+1] = vertpa[v2];
+       df2->v1 = GET_ES(v1, v2)
+       df2->v2 = v2;
+       df2->v3 = GET_ES(v2, v3)
+       df2->v4 = 0;
+       df2->flag &= ~ME_FACE_SEL;
+
+       facepa[cur+2] = vertpa[v3];
+       df3->v1 = GET_ES(v1, v3)
+       df3->v2 = GET_ES(v2, v3)
+       df3->v3 = v3;
+       df3->v4 = 0;
+       df3->flag &= ~ME_FACE_SEL;
+}
+
+static void remap_uvs_23(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
+{
+       MTFace *mf, *df1, *df2, *df3;
+       int l;
+
+       for(l=0; l<numlayer; l++) {
+               mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+               df1 = mf+cur;
+               df2 = df1 + 1;
+               df3 = df1 + 2;
+               mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+               mf += i;
+
+               copy_v2_v2(df1->uv[0], mf->uv[c0]);
+               INT_UV(df1->uv[1], c0, c1)
+               INT_UV(df1->uv[2], c1, c2)
+               INT_UV(df1->uv[3], c0, c2)
+
+               INT_UV(df2->uv[0], c0, c1)
+               copy_v2_v2(df2->uv[1], mf->uv[c1]);
+               INT_UV(df2->uv[2], c1, c2)
+
+               INT_UV(df2->uv[0], c0, c2)
+               INT_UV(df2->uv[1], c1, c2)
+               copy_v2_v2(df2->uv[2], mf->uv[c2]);
+       }
+}
+
+static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm){
        DerivedMesh *splitdm;
-       MFace *mf=0,*df1=0,*df2=0,*df3=0;
+       MFace *mf=NULL,*df1=NULL,*df2=NULL,*df3=NULL,*df4=NULL;
        MFace *mface=dm->getFaceArray(dm);
+       MTFace *mtf = NULL, *dtf1=NULL, *dtf2=NULL, *dtf3=NULL, *dtf4=NULL;
        MVert *dupve, *mv;
        EdgeHash *edgehash;
        EdgeHashIterator *ehi;
@@ -199,7 +554,8 @@ static DerivedMesh * splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
        int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2");
        int *facepa = emd->facepa;
        int *fs, totesplit=0,totfsplit=0,totin=0,curdupface=0,curdupin=0;
-       int i,j,v1,v2,v3,v4,esplit;
+       int i,j,v1,v2,v3,v4,esplit, v[4], uv[4];
+       int numlayer;
 
        edgehash= BLI_edgehash_new();
 
@@ -214,52 +570,48 @@ static DerivedMesh * splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
 
        /* mark edges for splitting and how to split faces */
        for (i=0,mf=mface,fs=facesplit; i<totface; i++,mf++,fs++) {
-               if(mf->v4){
-                       v1=vertpa[mf->v1];
-                       v2=vertpa[mf->v2];
-                       v3=vertpa[mf->v3];
-                       v4=vertpa[mf->v4];
+               v1=vertpa[mf->v1];
+               v2=vertpa[mf->v2];
+               v3=vertpa[mf->v3];
 
-                       if(v1!=v2){
-                               BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL);
-                               (*fs)++;
-                       }
+               if(v1!=v2){
+                       BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL);
+                       (*fs) |= 1;
+               }
 
-                       if(v2!=v3){
-                               BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL);
-                               (*fs)++;
-                       }
+               if(v2!=v3){
+                       BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL);
+                       (*fs) |= 2;
+               }
+
+               if(mf->v4){
+                       v4=vertpa[mf->v4];
 
                        if(v3!=v4){
                                BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL);
-                               (*fs)++;
+                               (*fs) |= 4;
                        }
 
                        if(v1!=v4){
                                BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL);
-                               (*fs)++;
+                               (*fs) |= 8;
                        }
 
-                       if(*fs==2){
-                               if((v1==v2 && v3==v4) || (v1==v4 && v2==v3))
-                                       *fs=1;
-                               else if(v1!=v2){
-                                       if(v1!=v4)
-                                               BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL);
-                                       else
-                                               BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL);
-                               }
-                               else{ 
-                                       if(v1!=v4)
-                                               BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL);
-                                       else
-                                               BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL);
-                               }
+                       /* mark center vertex as a fake edge split */
+                       if(*fs == 15)
+                               BLI_edgehash_insert(edgehash, mf->v1, mf->v3, NULL);
+               }
+               else {
+                       (*fs) |= 16; /* mark face as tri */
+
+                       if(v1!=v3){
+                               BLI_edgehash_insert(edgehash, mf->v1, mf->v3, NULL);
+                               (*fs) |= 4;
                        }
                }
        }
 
-       /* count splits & reindex */
+       /* count splits & create indexes for new verts */
        ehi= BLI_edgehashIterator_new(edgehash);
        totesplit=totvert;
        for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
@@ -269,24 +621,11 @@ static DerivedMesh * splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
        BLI_edgehashIterator_free(ehi);
 
        /* count new faces due to splitting */
-       for(i=0,fs=facesplit; i<totface; i++,fs++){
-               if(*fs==1)
-                       totfsplit+=1;
-               else if(*fs==2)
-                       totfsplit+=2;
-               else if(*fs==3)
-                       totfsplit+=3;
-               else if(*fs==4){
-                       totfsplit+=3;
-
-                       mf=dm->getFaceData(dm,i,CD_MFACE);//CDDM_get_face(dm,i);
-
-                       if(vertpa[mf->v1]!=vertpa[mf->v2] && vertpa[mf->v2]!=vertpa[mf->v3])
-                               totin++;
-               }
-       }
+       for(i=0,fs=facesplit; i<totface; i++,fs++)
+               totfsplit += add_faces[*fs];
        
-       splitdm= CDDM_from_template(dm, totesplit+totin, dm->getNumEdges(dm),totface+totfsplit);
+       splitdm= CDDM_from_template(dm, totesplit, 0, totface+totfsplit);
+       numlayer = CustomData_number_of_layers(&splitdm->faceData, CD_MTFACE);
 
        /* copy new faces & verts (is it really this painful with custom data??) */
        for(i=0; i<totvert; i++){
@@ -298,19 +637,10 @@ static DerivedMesh * splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
                DM_copy_vert_data(dm, splitdm, i, i, 1);
                *dest = source;
        }
-       for(i=0; i<totface; i++){
-               MFace source;
-               MFace *dest;
-               dm->getFace(dm, i, &source);
-               dest = CDDM_get_face(splitdm, i);
-
-               DM_copy_face_data(dm, splitdm, i, i, 1);
-               *dest = source;
-       }
 
        /* override original facepa (original pointer is saved in caller function) */
        facepa= MEM_callocN(sizeof(int)*(totface+totfsplit),"explode_facepa");
-       memcpy(facepa,emd->facepa,totface*sizeof(int));
+       //memcpy(facepa,emd->facepa,totface*sizeof(int));
        emd->facepa=facepa;
 
        /* create new verts */
@@ -333,320 +663,101 @@ static DerivedMesh * splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
        BLI_edgehashIterator_free(ehi);
 
        /* create new faces */
-       curdupface=totface;
-       curdupin=totesplit;
+       curdupface=0;//=totface;
+       //curdupin=totesplit;
        for(i=0,fs=facesplit; i<totface; i++,fs++){
-               if(*fs){
-                       mf=CDDM_get_face(splitdm,i);
-
-                       v1=vertpa[mf->v1];
-                       v2=vertpa[mf->v2];
-                       v3=vertpa[mf->v3];
-                       v4=vertpa[mf->v4];
-                       /* ouch! creating new faces & remapping them to new verts is no fun */
-                       if(*fs==1){
-                               df1=CDDM_get_face(splitdm,curdupface);
-                               DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                               *df1=*mf;
-                               curdupface++;
-                               
-                               if(v1==v2){
-                                       df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
-                                       df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
-                                       mf->v3=df1->v2;
-                                       mf->v4=df1->v1;
-                               }
-                               else{
-                                       df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                       df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4);
-                                       mf->v2=df1->v1;
-                                       mf->v3=df1->v4;
-                               }
-
-                               facepa[i]=v1;
-                               facepa[curdupface-1]=v3;
-
-                               test_index_face(df1, &splitdm->faceData, curdupface, (df1->v4 ? 4 : 3));
-                       }
-                       if(*fs==2){
-                               df1=CDDM_get_face(splitdm,curdupface);
-                               DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                               *df1=*mf;
-                               curdupface++;
-
-                               df2=CDDM_get_face(splitdm,curdupface);
-                               DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                               *df2=*mf;
-                               curdupface++;
-
-                               if(v1!=v2){
-                                       if(v1!=v4){
-                                               df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
-                                               df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                               df2->v1=df1->v3=mf->v2;
-                                               df2->v3=df1->v4=mf->v4;
-                                               df2->v2=mf->v3;
-
-                                               mf->v2=df1->v2;
-                                               mf->v3=df1->v1;
-
-                                               df2->v4=mf->v4=0;
-
-                                               facepa[i]=v1;
-                                       }
-                                       else{
-                                               df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                               df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
-                                               df1->v4=mf->v3;
-                                               df2->v2=mf->v3;
-                                               df2->v3=mf->v4;
-
-                                               mf->v1=df1->v2;
-                                               mf->v3=df1->v3;
-
-                                               df2->v4=mf->v4=0;
-
-                                               facepa[i]=v2;
-                                       }
-                                       facepa[curdupface-1]=facepa[curdupface-2]=v3;
-                               }
-                               else{
-                                       if(v1!=v4){
-                                               df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-                                               df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
-                                               df1->v2=mf->v3;
-
-                                               mf->v1=df1->v4;
-                                               mf->v2=df1->v3;
-                                               mf->v3=mf->v4;
-
-                                               df2->v4=mf->v4=0;
-
-                                               facepa[i]=v4;
-                                       }
-                                       else{
-                                               df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
-                                               df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4);
-                                               df1->v1=mf->v4;
-                                               df1->v2=mf->v2;
-                                               df2->v3=mf->v4;
-
-                                               mf->v1=df1->v4;
-                                               mf->v2=df1->v3;
-
-                                               df2->v4=mf->v4=0;
-
-                                               facepa[i]=v3;
-                                       }
-
-                                       facepa[curdupface-1]=facepa[curdupface-2]=v1;
-                               }
-
-                               test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
-                               test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
-                       }
-                       else if(*fs==3){
-                               df1=CDDM_get_face(splitdm,curdupface);
-                               DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                               *df1=*mf;
-                               curdupface++;
-
-                               df2=CDDM_get_face(splitdm,curdupface);
-                               DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                               *df2=*mf;
-                               curdupface++;
-
-                               df3=CDDM_get_face(splitdm,curdupface);
-                               DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                               *df3=*mf;
-                               curdupface++;
-
-                               if(v1==v2){
-                                       df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
-                                       df3->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
-                                       df3->v3=df2->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-                                       df3->v2=mf->v3;
-                                       df2->v3=mf->v4;
-                                       df1->v4=df2->v4=df3->v4=0;
-
-                                       mf->v3=df1->v2;
-                                       mf->v4=df1->v1;
-
-                                       facepa[i]=facepa[curdupface-3]=v1;
-                                       facepa[curdupface-1]=v3;
-                                       facepa[curdupface-2]=v4;
-                               }
-                               else if(v2==v3){
-                                       df3->v1=df2->v3=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
-                                       df2->v2=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                       df3->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-
-                                       df3->v3=mf->v4;
-                                       df2->v1=mf->v1;
-                                       df1->v4=df2->v4=df3->v4=0;
-
-                                       mf->v1=df1->v2;
-                                       mf->v4=df1->v3;
-
-                                       facepa[i]=facepa[curdupface-3]=v2;
-                                       facepa[curdupface-1]=v4;
-                                       facepa[curdupface-2]=v1;
-                               }
-                               else if(v3==v4){
-                                       df3->v2=df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                       df2->v3=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
-                                       df3->v3=df1->v3=edgesplit_get(edgehash, mf->v1, mf->v4);
-
-                                       df3->v1=mf->v1;
-                                       df2->v2=mf->v2;
-                                       df1->v4=df2->v4=df3->v4=0;
-
-                                       mf->v1=df1->v3;
-                                       mf->v2=df1->v2;
-
-                                       facepa[i]=facepa[curdupface-3]=v3;
-                                       facepa[curdupface-1]=v1;
-                                       facepa[curdupface-2]=v2;
-                               }
-                               else{
-                                       df3->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                       df3->v3=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
-                                       df2->v3=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-
-                                       df3->v2=mf->v2;
-                                       df2->v2=mf->v3;
-                                       df1->v4=df2->v4=df3->v4=0;
-
-                                       mf->v2=df1->v1;
-                                       mf->v3=df1->v3;
-
-                                       facepa[i]=facepa[curdupface-3]=v1;
-                                       facepa[curdupface-1]=v2;
-                                       facepa[curdupface-2]=v3;
-                               }
-
-                               test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
-                               test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
-                               test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
-                       }
-                       else if(*fs==4){
-                               if(v1!=v2 && v2!=v3){
-
-                                       /* set new vert to face center */
-                                       mv=CDDM_get_vert(splitdm,mf->v1);
-                                       dupve=CDDM_get_vert(splitdm,curdupin);
-                                       DM_copy_vert_data(splitdm,splitdm,mf->v1,curdupin,1);
-                                       *dupve=*mv;
-
-                                       mv=CDDM_get_vert(splitdm,mf->v2);
-                                       VECADD(dupve->co,dupve->co,mv->co);
-                                       mv=CDDM_get_vert(splitdm,mf->v3);
-                                       VECADD(dupve->co,dupve->co,mv->co);
-                                       mv=CDDM_get_vert(splitdm,mf->v4);
-                                       VECADD(dupve->co,dupve->co,mv->co);
-                                       mul_v3_fl(dupve->co,0.25);
-
-
-                                       df1=CDDM_get_face(splitdm,curdupface);
-                                       DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                                       *df1=*mf;
-                                       curdupface++;
-
-                                       df2=CDDM_get_face(splitdm,curdupface);
-                                       DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                                       *df2=*mf;
-                                       curdupface++;
-
-                                       df3=CDDM_get_face(splitdm,curdupface);
-                                       DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                                       *df3=*mf;
-                                       curdupface++;
-
-                                       df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                       df3->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
-
-                                       df2->v1=edgesplit_get(edgehash, mf->v1, mf->v4);
-                                       df3->v4=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-
-                                       df3->v1=df2->v2=df1->v4=curdupin;
-
-                                       mf->v2=df1->v1;
-                                       mf->v3=curdupin;
-                                       mf->v4=df2->v1;
-
-                                       curdupin++;
-
-                                       facepa[i]=v1;
-                                       facepa[curdupface-3]=v2;
-                                       facepa[curdupface-2]=v3;
-                                       facepa[curdupface-1]=v4;
-
-                                       test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
-
-                                       test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
-                                       test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
-                               }
-                               else{
-                                       df1=CDDM_get_face(splitdm,curdupface);
-                                       DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                                       *df1=*mf;
-                                       curdupface++;
-
-                                       df2=CDDM_get_face(splitdm,curdupface);
-                                       DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                                       *df2=*mf;
-                                       curdupface++;
-
-                                       df3=CDDM_get_face(splitdm,curdupface);
-                                       DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
-                                       *df3=*mf;
-                                       curdupface++;
-
-                                       if(v2==v3){
-                                               df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                               df3->v1=df1->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3);
-                                               df2->v1=df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
-
-                                               df3->v3=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-
-                                               df3->v2=mf->v3;
-                                               df3->v4=0;
-
-                                               mf->v2=df1->v1;
-                                               mf->v3=df1->v4;
-                                               mf->v4=0;
-
-                                               facepa[i]=v1;
-                                               facepa[curdupface-3]=facepa[curdupface-2]=v2;
-                                               facepa[curdupface-1]=v3;
-                                       }
-                                       else{
-                                               df3->v1=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2);
-                                               df2->v4=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4);
-                                               df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4);
-
-                                               df3->v3=df2->v2=edgesplit_get(edgehash, mf->v2, mf->v3);
-
-                                               df3->v4=0;
-
-                                               mf->v1=df1->v4;
-                                               mf->v2=df1->v3;
-                                               mf->v3=mf->v4;
-                                               mf->v4=0;
-
-                                               facepa[i]=v4;
-                                               facepa[curdupface-3]=facepa[curdupface-2]=v1;
-                                               facepa[curdupface-1]=v2;
-                                       }
-
-                                       test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3));
-                                       test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3));
-                                       test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
-                               }
-                       }
+               mf = dm->getFaceData(dm, i, CD_MFACE);
+
+               switch(*fs) {
+               case 3:
+               case 10:
+               case 11:
+               case 15:
+                       SET_VERTS(1, 2, 3, 4)
+                       break;
+               case 5:
+               case 6:
+               case 7:
+                       SET_VERTS(2, 3, 4, 1)
+                       break;
+               case 9:
+               case 13:
+                       SET_VERTS(4, 1, 2, 3)
+                       break;
+               case 12:
+               case 14:
+                       SET_VERTS(3, 4, 1, 2)
+                       break;
+               case 21:
+               case 23:
+                       SET_VERTS(1, 2, 3, 4)
+                       break;
+               case 19:
+                       SET_VERTS(2, 3, 1, 4)
+                       break;
+               case 22:
+                       SET_VERTS(3, 1, 2, 4)
+                       break;
+               }
 
-                       test_index_face(df1, &splitdm->faceData, i, (df1->v4 ? 4 : 3));
+               switch(*fs) {
+               case 3:
+               case 6:
+               case 9:
+               case 12:
+                       remap_faces_3_6_9_12(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
+                       if(numlayer)
+                               remap_uvs_3_6_9_12(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+                       break;
+               case 5:
+               case 10:
+                       remap_faces_5_10(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
+                       if(numlayer)
+                               remap_uvs_5_10(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+                       break;
+               case 15:
+                       remap_faces_15(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
+                       if(numlayer)
+                               remap_uvs_15(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+                       break;
+               case 7:
+               case 11:
+               case 13:
+               case 14:
+                       remap_faces_7_11_13_14(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
+                       if(numlayer)
+                               remap_uvs_7_11_13_14(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+                       break;
+               case 19:
+               case 21:
+               case 22:
+                       remap_faces_19_21_22(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
+                       if(numlayer)
+                               remap_uvs_19_21_22(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
+                       break;
+               case 23:
+                       remap_faces_23(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
+                       if(numlayer)
+                               remap_uvs_23(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
+                       break;
+               case 0:
+               case 16:
+                       df1 = get_dface(dm, splitdm, curdupface, i, mf);
+                       facepa[curdupface] = vertpa[mf->v1];
+
+                       if(df1->v4)
+                               df1->flag |= ME_FACE_SEL;
+                       else
+                               df1->flag &= ~ME_FACE_SEL;
+                       break;
                }
+
+               curdupface += add_faces[*fs]+1;
+       }
+
+       for(i=0; i<curdupface; i++) {
+               mf = CDDM_get_face(splitdm, i);
+               test_index_face(mf, &splitdm->faceData, i, (mf->flag & ME_FACE_SEL ? 4 : 3));
        }
 
        BLI_edgehash_free(edgehash, NULL);
@@ -675,6 +786,7 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
        int *facepa=emd->facepa;
        int totdup=0,totvert=0,totface=0,totpart=0;
        int i, j, v, mindex=0;
+       MTFace *mtface = NULL, *mtf;
 
        totface= dm->getNumFaces(dm);
        totvert= dm->getNumVerts(dm);
@@ -724,6 +836,7 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
 
        /* the final duplicated vertices */
        explode= CDDM_from_template(dm, totdup, 0,totface);
+       mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
        /*dupvert= CDDM_get_verts(explode);*/
 
        /* getting back to object space */
@@ -800,16 +913,28 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
                else 
                        mindex = totvert+facepa[i];
 
-               source.v1 = edgesplit_get(vertpahash, source.v1, mindex);
-               source.v2 = edgesplit_get(vertpahash, source.v2, mindex);
-               source.v3 = edgesplit_get(vertpahash, source.v3, mindex);
+               source.v1 = edgecut_get(vertpahash, source.v1, mindex);
+               source.v2 = edgecut_get(vertpahash, source.v2, mindex);
+               source.v3 = edgecut_get(vertpahash, source.v3, mindex);
                if(source.v4)
-                       source.v4 = edgesplit_get(vertpahash, source.v4, mindex);
+                       source.v4 = edgecut_get(vertpahash, source.v4, mindex);
 
                DM_copy_face_data(dm,explode,i,i,1);
 
                *mf = source;
 
+               /* override uv channel for particle age */
+               if(mtface) {
+                       float age = (cfra - pa->time)/pa->lifetime;
+                       /* Clamp to this range to avoid flipping to the other side of the coordinates. */
+                       CLAMP(age, 0.001f, 0.999f);
+
+                       mtf = mtface + i;
+
+                       mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age;
+                       mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f;
+               }
+
                test_index_face(mf, &explode->faceData, i, (orig_v4 ? 4 : 3));
        }
 
@@ -870,9 +995,9 @@ static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
                        createFacepa(emd,psmd,derivedData);
                }
                                 /* 2. create new mesh */
-                                if(emd->flag & eExplodeFlag_EdgeSplit){
+                                if(emd->flag & eExplodeFlag_EdgeCut){
                                         int *facepa = emd->facepa;
-                                        DerivedMesh *splitdm=splitEdges(emd,dm);
+                                        DerivedMesh *splitdm=cutEdges(emd,dm);
                                         DerivedMesh *explode=explodeMesh(emd, psmd, md->scene, ob, splitdm);
 
                                         MEM_freeN(emd->facepa);