particle puff, volume option.

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.
This commit is contained in:
Campbell Barton 2010-01-12 16:35:34 +00:00
parent e672a083d9
commit b8d743c9c6
4 changed files with 64 additions and 9 deletions

@ -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 #

@ -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);
VECADDFAC(kco, rootco, nor, length);
/* blend between the current and straight position */
VECSUB(dco, kco, co);
VECADDFAC(co, co, dco, fac);
/* blend between the current and straight position */
VECSUB(dco, kco, co);
VECADDFAC(co, co, dco, fac);
/* re-use dco to compare before and after translation and add to the offset */
VECCOPY(dco, key->co);
VECCOPY(key->co, co);
mul_m4_v3(imat, key->co);
mul_v3_m4v3(key->co, imat, 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)

@ -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

@ -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);