Particle Edit Mode
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 20 Dec 2007 17:04:10 +0000 (17:04 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 20 Dec 2007 17:04:10 +0000 (17:04 +0000)
==================

- Added a Remove Doubles tool, to remove two particles with the
  same root position.

source/blender/include/BIF_editparticle.h
source/blender/src/editobject.c
source/blender/src/editparticle.c
source/blender/src/header_view3d.c

index 08f5813560f0312386868d3edd8d488c65f35bce..77fb091de3798369d088e87a615e16e6b6f2bd76 100644 (file)
@@ -82,6 +82,7 @@ void PE_delete_particle(void);
 void PE_remove_doubles(void);
 void PE_mirror_x(int tagged);
 void PE_selectbrush_menu(void);
+void PE_remove_doubles(void);
 
 /* undo */
 void PE_undo_push(char *str);
index bb3beb329f1ad93615a40e6b3a7bb54b89e8e9a3..c563548759c1addb2671a582d4760906da0aac09 100644 (file)
@@ -2296,9 +2296,9 @@ void special_editmenu(void)
                                return;
 
                        if(G.scene->selectmode & SCE_SELECT_POINT)
-                               nr= pupmenu("Specials%t|Rekey%x1|Subdivide%x2|Select First%x3|Select Last%x4");
+                               nr= pupmenu("Specials%t|Rekey%x1|Subdivide%x2|Select First%x3|Select Last%x4|Remove Doubles%x5");
                        else
-                               nr= pupmenu("Specials%t|Rekey%x1");
+                               nr= pupmenu("Specials%t|Rekey%x1|Remove Doubles%x5");
                        
                        switch(nr) {
                        case 1:
@@ -2315,6 +2315,9 @@ void special_editmenu(void)
                        case 4:
                                PE_select_tip();
                                break;
+                       case 5:
+                               PE_remove_doubles();
+                               break;
                        }
                        
                        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
index 0475e91f2b7471161550042f26f5cc6a0136189c..f07012c463db481b997a1b398f91f2c901a98d53 100644 (file)
@@ -83,6 +83,7 @@
 #include "BIF_resources.h"
 #include "BIF_screen.h"
 #include "BIF_space.h"
+#include "BIF_toolbox.h"
 
 #include "BSE_view.h"
 
@@ -1901,6 +1902,83 @@ void PE_subdivide(void)
        
        BIF_undo_push("Subdivide hair(s)");
 }
+void PE_remove_doubles(void)
+{
+       Object *ob=OBACT;
+       ParticleSystem *psys=PE_get_current(ob);
+       ParticleEditSettings *pset=PE_settings();
+       ParticleData *pa;
+       ParticleEdit *edit;
+       ParticleSystemModifierData *psmd;
+       KDTree *tree;
+       KDTreeNearest nearest[10];
+       float mat[4][4], co[3];
+       int i, n, totn, removed, totpart, flag, totremoved;
+
+       if(!PE_can_edit(psys)) return;
+
+       edit= psys->edit;
+       psmd= psys_get_modifier(ob, psys);
+       totremoved= 0;
+
+       do {
+               removed= 0;
+
+               totpart= psys->totpart;
+               tree=BLI_kdtree_new(totpart);
+                       
+               /* insert particles into kd tree */
+               LOOP_PARTICLES(i,pa) {
+                       if(particle_is_selected(psys, pa)) {
+                               psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
+                               VECCOPY(co, pa->hair[0].co);
+                               Mat4MulVecfl(mat, co);
+                               BLI_kdtree_insert(tree, i, co, NULL);
+                       }
+               }
+
+               BLI_kdtree_balance(tree);
+
+               /* tag particles to be removed */
+               LOOP_PARTICLES(i,pa) {
+                       if(particle_is_selected(psys, pa)) {
+                               psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
+                               VECCOPY(co, pa->hair[0].co);
+                               Mat4MulVecfl(mat, co);
+
+                               totn= BLI_kdtree_find_n_nearest(tree,10,co,NULL,nearest);
+
+                               for(n=0; n<totn; n++) {
+                                       /* this needs a custom threshold still */
+                                       if(nearest[n].index > i && nearest[n].dist < 0.0002f) {
+                                               if(!(pa->flag & PARS_TAG)) {
+                                                       pa->flag |= PARS_TAG;
+                                                       removed++;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               BLI_kdtree_free(tree);
+
+               /* remove tagged particles - don't do mirror here! */
+               flag= pset->flag;
+               pset->flag &= ~PE_X_MIRROR;
+               remove_tagged_elements(ob, psys);
+               pset->flag= flag;
+               totremoved += removed;
+       } while(removed);
+
+       if(totremoved)
+               notice("Removed: %d", totremoved);
+
+       PE_recalc_world_cos(ob, psys);
+       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+       allqueue(REDRAWVIEW3D, 1);
+       BIF_undo_push("Remove double particles");
+}
+
 /************************************************/
 /*                     Edit Brushes                                            */
 /************************************************/
index 3a86a55a0aa3c500df04a59efac8a2b39635d39a..95f24c340987f6ee5330d5762f23d96d09b61346 100644 (file)
@@ -4691,6 +4691,9 @@ void do_view3d_particlemenu(void *arg, int event)
        case 6:
                pset->flag ^= PE_X_MIRROR;
                break;
+       case 7:
+               PE_remove_doubles();
+               break;
        }
 
        allqueue(REDRAWVIEW3D, 0);
@@ -4713,6 +4716,7 @@ uiBlock *view3d_particlemenu(void *arg_unused)
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Mirror|Ctrl M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
        uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove Doubles|W, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete...|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
        if(G.scene->selectmode & SCE_SELECT_POINT)
                uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");