particle puff, volume option.
authorCampbell Barton <ideasman42@gmail.com>
Tue, 12 Jan 2010 16:35:34 +0000 (16:35 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 12 Jan 2010 16:35:34 +0000 (16:35 +0000)
When combing long hair  it will often end up with no volume (flat on the head like its wet).
a way to fix this is to use the puff tool however when applied points at the root only this just gives a bit of volume at the roots and the rest of the hair stays flat.

This option moves the unselected parts of the hair without applying the puff tool to them, giving volume to the hair whilst preserving the desired style.

release/scripts/ui/space_view3d_toolbar.py
source/blender/editors/physics/particle_edit.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_sculpt_paint.c

index a7a8968fb055ce6273c3d8dea04a42acc07f5e99..6d0b34cc7c86f0ae98f8aad048a8f4a01ee0472e 100644 (file)
@@ -533,6 +533,7 @@ class VIEW3D_PT_tools_brush(PaintPanel):
                 layout.prop(brush, "length_mode", expand=True)
             elif settings.tool == 'PUFF':
                 layout.prop(brush, "puff_mode", expand=True)
+                layout.prop(brush, "use_puff_volume")
 
         # Sculpt Mode #
 
index 7c67b261cafe0ba7c4e31a3cff9da625bffd1e59..fc86971b8accad6957d493598e5f7c5c3ffe1653 100644 (file)
@@ -2846,7 +2846,15 @@ static void brush_puff(PEData *data, int point_index)
        float mat[4][4], imat[4][4];
        float obmat[4][4], obimat[4][4];
 
-       float lastco[3], rootco[3] = {0.0f, 0.0f, 0.0f}, co[3], nor[3], kco[3], dco[3], fac=0.0f, length=0.0f;
+       float lastco[3], rootco[3] = {0.0f, 0.0f, 0.0f}, co[3], nor[3], kco[3], dco[3], ofs[3] = {0.0f, 0.0f, 0.0f}, fac=0.0f, length=0.0f;
+       int puff_volume = 0;
+       int change= 0;
+
+       {
+               ParticleEditSettings *pset= PE_settings(data->scene);
+               ParticleBrushData *brush= &pset->brush[pset->brushtype];
+               puff_volume = brush->flag & PE_BRUSH_DATA_PUFF_VOLUME;
+       }
 
        if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
                psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat);
@@ -2883,24 +2891,62 @@ static void brush_puff(PEData *data, int point_index)
                                fac= -fac;
                }
                else {
-                       /* compute position as if hair was standing up straight */
+                       /* compute position as if hair was standing up straight.
+                        * */
                        VECCOPY(lastco, co);
                        VECCOPY(co, key->co);
                        mul_m4_v3(mat, co);
                        length += len_v3v3(lastco, co);
+                       if((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE)) {
+                               VECADDFAC(kco, rootco, nor, length);
+
+                               /* blend between the current and straight position */
+                               VECSUB(dco, kco, co);
+                               VECADDFAC(co, co, dco, fac);
 
-                       VECADDFAC(kco, rootco, nor, length);
+                               /* re-use dco to compare before and after translation and add to the offset  */
+                               VECCOPY(dco, key->co);
 
-                       /* blend between the current and straight position */
-                       VECSUB(dco, kco, co);
-                       VECADDFAC(co, co, dco, fac);
+                               mul_v3_m4v3(key->co, imat, co);
 
-                       VECCOPY(key->co, co);
-                       mul_m4_v3(imat, key->co);
+                               if(puff_volume) {
+                                       /* accumulate the total distance moved to apply to unselected
+                                        * keys that come after */
+                                       ofs[0] += key->co[0] - dco[0];
+                                       ofs[1] += key->co[1] - dco[1];
+                                       ofs[2] += key->co[2] - dco[2];
+                               }
+                               change = 1;
+                       }
+                       else {
+
+                               if(puff_volume) {
+#if 0
+                                       /* this is simple but looks bad, adds annoying kinks */
+                                       add_v3_v3(key->co, ofs);
+#else
+                                       /* translate (not rotate) the rest of the hair if its not selected  */
+                                       if(ofs[0] || ofs[1] || ofs[2]) {
+                                               float c1[3], c2[3];
+                                               VECSUB(dco, lastco, co);
+                                               mul_m4_v3(imat, dco); /* into particle space */
+
+                                               /* move the point allong a vector perpendicular to the
+                                                * hairs direction, reduces odd kinks, */
+                                               cross_v3_v3v3(c1, ofs, dco);
+                                               cross_v3_v3v3(c2, c1, dco);
+                                               normalize_v3(c2);
+                                               mul_v3_fl(c2, len_v3(ofs));
+                                               add_v3_v3(key->co, c2);
+                                       }
+#endif
+                               }
+                       }
                }
        }
 
-       point->flag |= PEP_EDIT_RECALC;
+       if(change)
+               point->flag |= PEP_EDIT_RECALC;
 }
 
 static void brush_smooth_get(PEData *data, float mat[][4], float imat[][4], int point_index, int key_index, PTCacheEditKey *key)
index 974967c6aa616056ee93c96df7aeb7a4aec60b35..a55d13cf1606c24cd11dab576dd38255bbd6a172 100644 (file)
@@ -521,6 +521,7 @@ typedef struct ImagePaintSettings {
 typedef struct ParticleBrushData {
        short size, strength;   /* common settings */
        short step, invert;             /* for specific brushes only */
+       int flag, pad;
 } ParticleBrushData;
 
 typedef struct ParticleEditSettings {
@@ -1140,6 +1141,9 @@ typedef enum SculptFlags {
 /* this must equal ParticleEditSettings.brush array size */
 #define PE_TOT_BRUSH           6
 
+/* ParticleBrushData->flag */
+#define PE_BRUSH_DATA_PUFF_VOLUME 1
+
 /* tooksettings->particle edittype */
 #define PE_TYPE_PARTICLES      0
 #define PE_TYPE_SOFTBODY       1
index 99bee9413cda309e30c45af04bf7606b9cb0f6c8..5e5eb9d84ceb31d9fe0713dac8fbfd84d85202a8 100644 (file)
@@ -527,6 +527,10 @@ static void rna_def_particle_edit(BlenderRNA *brna)
        RNA_def_property_enum_items(prop, puff_mode);
        RNA_def_property_ui_text(prop, "Puff Mode", "");
 
+       prop= RNA_def_property(srna, "use_puff_volume", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_BRUSH_DATA_PUFF_VOLUME);
+       RNA_def_property_ui_text(prop, "Puff Volume", "Apply puff to unselected end-points, (helps maintain hair volume when puffing root)");
+
        prop= RNA_def_property(srna, "length_mode", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "invert");
        RNA_def_property_enum_items(prop, length_mode);