Particles: patch #35205 by Jakub Zolcik
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 27 May 2013 17:11:05 +0000 (17:11 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 27 May 2013 17:11:05 +0000 (17:11 +0000)
The Emission panel now has a Use Modifier Stack option to emit particles from
the mesh with modifiers applied. Previously particles would only be emitted from
faces that exist in the original mesh. There are some caveats however:
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.68/Tools#Particles

release/scripts/startup/bl_ui/properties_particle.py
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_particle.c

index f949cbd974587e61588c570435083b85911bc0ab..931b47896a626cd659cbe349e06530df8064a98b 100644 (file)
@@ -213,6 +213,9 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
 
         if part.type == 'HAIR' and not part.use_advanced_hair:
             row.prop(part, "hair_length")
+
+            row = layout.row()
+            row.prop(part, "use_modifier_stack")
             return
 
         if part.type != 'HAIR':
@@ -250,6 +253,9 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
                 row.prop(part, "grid_resolution")
                 row.prop(part, "grid_random", text="Random", slider=True)
 
+        row = layout.row()
+        row.prop(part, "use_modifier_stack")
+
 
 class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
     bl_label = "Hair dynamics"
index a95afe14a483b8ce5479539e581626ad47a28f61..3ab535febb121a0246c5e642c37cfcdbc4dcbd21 100644 (file)
@@ -3636,6 +3636,8 @@ static void default_particle_settings(ParticleSettings *part)
 
        if (!part->effector_weights)
                part->effector_weights = BKE_add_effector_weights(NULL);
+
+       part->use_modifier_stack = false;
 }
 
 
index eb95ca16fc3f77939963d5d61699ee8ceb32a117..81c7fc44715b99ea39c3788e76b121996ac8c2e3 100644 (file)
@@ -341,6 +341,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
         *            each original elements can reference its derived elements
         */
        Mesh *me= (Mesh*)ob->data;
+       bool use_modifier_stack= psys->part->use_modifier_stack;
        PARTICLE_P;
        
        /* CACHE LOCATIONS */
@@ -351,17 +352,33 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
 
                if (psys->part->from == PART_FROM_VERT) {
                        totdmelem= dm->getNumVerts(dm);
-                       totelem= me->totvert;
-                       origindex= dm->getVertDataArray(dm, CD_ORIGINDEX);
+
+                       if (use_modifier_stack) {
+                               totelem= totdmelem;
+                               origindex= NULL;
+                       }
+                       else {
+                               totelem= me->totvert;
+                               origindex= dm->getVertDataArray(dm, CD_ORIGINDEX);
+                       }
                }
                else { /* FROM_FACE/FROM_VOLUME */
                        totdmelem= dm->getNumTessFaces(dm);
-                       totelem= me->totpoly;
-                       origindex = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
-                       /* for face lookups we need the poly origindex too */
-                       origindex_poly = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-                       if (origindex_poly == NULL) {
-                               origindex = NULL;
+
+                       if (use_modifier_stack) {
+                               totelem= totdmelem;
+                               origindex= NULL;
+                               origindex_poly= NULL;
+                       }
+                       else {
+                               totelem= me->totpoly;
+                               origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+
+                               /* for face lookups we need the poly origindex too */
+                               origindex_poly= dm->getPolyDataArray(dm, CD_ORIGINDEX);
+                               if (origindex_poly == NULL) {
+                                       origindex= NULL;
+                               }
                        }
                }
        
@@ -373,11 +390,16 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                        node->link = SET_INT_IN_POINTER(i);
 
                        /* may be vertex or face origindex */
-                       origindex_final = origindex ? origindex[i] : ORIGINDEX_NONE;
+                       if (use_modifier_stack) {
+                               origindex_final = i;
+                       }
+                       else {
+                               origindex_final = origindex ? origindex[i] : ORIGINDEX_NONE;
 
-                       /* if we have a poly source, do an index lookup */
-                       if (origindex_poly && origindex_final != ORIGINDEX_NONE) {
-                               origindex_final = origindex_poly[origindex_final];
+                               /* if we have a poly source, do an index lookup */
+                               if (origindex_poly && origindex_final != ORIGINDEX_NONE) {
+                                       origindex_final = origindex_poly[origindex_final];
+                               }
                        }
 
                        if (origindex_final != ORIGINDEX_NONE) {
@@ -395,18 +417,27 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                /* cache the verts/faces! */
                LOOP_PARTICLES {
                        if (pa->num < 0) {
-                               pa->num_dmcache = -1;
+                               pa->num_dmcache = DMCACHE_NOTFOUND;
                                continue;
                        }
 
                        if (psys->part->from == PART_FROM_VERT) {
-                               if (nodearray[pa->num])
+                               if (pa->num < totelem && nodearray[pa->num])
                                        pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link);
+                               else
+                                       pa->num_dmcache = DMCACHE_NOTFOUND;
                        }
                        else { /* FROM_FACE/FROM_VOLUME */
                                /* Note that sometimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this,
                                 * but for now passing NULL is OK. every face will be searched for the particle so its slower - Campbell */
-                               pa->num_dmcache= psys_particle_dm_face_lookup(ob, dm, pa->num, pa->fuv, pa->num < totelem ? nodearray[pa->num] : NULL);
+                               if (use_modifier_stack) {
+                                       if (pa->num < totelem && nodearray[pa->num])
+                                               pa->num_dmcache = GET_INT_FROM_POINTER(nodearray[pa->num]->link);
+                                       else
+                                               pa->num_dmcache = DMCACHE_NOTFOUND;
+                               }
+                               else
+                                       pa->num_dmcache= psys_particle_dm_face_lookup(ob, dm, pa->num, pa->fuv, pa->num < totelem ? nodearray[pa->num] : NULL);
                        }
                }
 
@@ -419,7 +450,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                 * an invalid value, just in case */
                
                LOOP_PARTICLES
-                       pa->num_dmcache = -1;
+                       pa->num_dmcache = DMCACHE_NOTFOUND;
        }
 }
 
@@ -1110,7 +1141,10 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
                distr = part->distr;
                BLI_srandom(31415926 + psys->seed);
                
-               dm= CDDM_from_mesh((Mesh*)ob->data, ob);
+               if (psys->part->use_modifier_stack)
+                       dm = finaldm;
+               else
+                       dm= CDDM_from_mesh((Mesh*)ob->data, ob);
 
                /* BMESH ONLY, for verts we don't care about tessfaces */
                if (from != PART_FROM_VERT) {
@@ -1118,7 +1152,8 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
                }
 
                /* we need orco for consistent distributions */
-               DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob));
+               if (!CustomData_has_layer(&dm->vertData, CD_ORCO))
+                       DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob));
 
                if (from == PART_FROM_VERT) {
                        MVert *mv= dm->getVertDataArray(dm, CD_MVERT);
index ec2a724ac82a4e68e04f9baebe37204c5096620f..84442201df82906681a6eb9487d31f3e6f99b96a 100644 (file)
@@ -243,6 +243,11 @@ typedef struct ParticleSettings {
        struct Ipo *ipo  DNA_DEPRECATED;  /* old animation system, deprecated for 2.5 */
        struct PartDeflect *pd;
        struct PartDeflect *pd2;
+
+       /* modified dm support */
+       short use_modifier_stack;
+       short pad[3];
+
 } ParticleSettings;
 
 typedef struct ParticleSystem {
index 158377f6a8fdc4411a2a4f92d60d96ac74286642..941437771f608d4179d950752fb5b4f425c76bbc 100644 (file)
@@ -2916,6 +2916,13 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Loop count", "Number of times the keys are looped");
        RNA_def_property_update(prop, 0, "rna_Particle_redo");
        
+       /* modified dm support */
+       prop = RNA_def_property(srna, "use_modifier_stack", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "use_modifier_stack", 0);
+       RNA_def_property_ui_text(prop, "Use Modifier Stack", "Emit particles from mesh with modifiers applied"
+                                      "(must use same subsurf level for viewport and render for correct results)");
+       RNA_def_property_update(prop, 0, "rna_Particle_change_type");
+
        /* draw objects & groups */
        prop = RNA_def_property(srna, "dupli_group", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "dup_group");