Curve-based control for "roughness" (noise displacement) of child hair.
authorLukas Tönne <lukas.toenne@gmail.com>
Fri, 9 Jan 2015 14:58:18 +0000 (15:58 +0100)
committerLukas Tönne <lukas.toenne@gmail.com>
Tue, 20 Jan 2015 08:30:09 +0000 (09:30 +0100)
release/scripts/startup/bl_ui/properties_particle.py
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_child.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_particle.c

index c5723ea4c711d66b2c8b2f98210715ef9accedee..b36ddab4762a5a0b72952f8fbe516904e38af1a0 100644 (file)
@@ -1196,20 +1196,28 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
             sub.prop(part, "child_parting_max", text="Max")
 
         col = split.column()
-        col.label(text="Roughness:")
 
-        sub = col.column(align=True)
-        sub.prop(part, "roughness_1", text="Uniform")
-        sub.prop(part, "roughness_1_size", text="Size")
+        col.prop(part, "use_roughness_curve")
+        if part.use_roughness_curve:
+            sub = col.column()
+            sub.template_curve_mapping(part, "roughness_curve")
+            sub.prop(part, "roughness_1", text="Roughness")
+            sub.prop(part, "roughness_1_size", text="Size")
+        else:
+            col.label(text="Roughness:")
 
-        sub = col.column(align=True)
-        sub.prop(part, "roughness_endpoint", "Endpoint")
-        sub.prop(part, "roughness_end_shape")
+            sub = col.column(align=True)
+            sub.prop(part, "roughness_1", text="Uniform")
+            sub.prop(part, "roughness_1_size", text="Size")
 
-        sub = col.column(align=True)
-        sub.prop(part, "roughness_2", text="Random")
-        sub.prop(part, "roughness_2_size", text="Size")
-        sub.prop(part, "roughness_2_threshold", slider=True)
+            sub = col.column(align=True)
+            sub.prop(part, "roughness_endpoint", "Endpoint")
+            sub.prop(part, "roughness_end_shape")
+
+            sub = col.column(align=True)
+            sub.prop(part, "roughness_2", text="Random")
+            sub.prop(part, "roughness_2_size", text="Size")
+            sub.prop(part, "roughness_2_threshold", slider=True)
 
         layout.row().label(text="Kink:")
         layout.row().prop(part, "kink", expand=True)
index cb7660824676963b0ef192df2e8eaaf6c485a18b..b0b605e40ca6b3c200f6b2d0ec8d5e7fb3dd3a05 100644 (file)
@@ -340,6 +340,7 @@ int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct Pa
 
 /* child paths */
 void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part);
+void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part);
 void psys_apply_child_modifiers(struct ParticleThreadContext *ctx, struct ListBase *modifiers,
                                 struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4],
                                 struct ParticleCacheKey *keys, struct ParticleCacheKey *parent_keys);
index 1001dde2561581c1b70f166d20e1c867d6abbfe3..2f0fbbb45eaf242e95298dd7d9aafc31c1377705 100644 (file)
@@ -377,6 +377,8 @@ void BKE_particlesettings_free(ParticleSettings *part)
        
        if (part->clumpcurve)
                curvemapping_free(part->clumpcurve);
+       if (part->roughcurve)
+               curvemapping_free(part->roughcurve);
        
        free_partdeflect(part->pd);
        free_partdeflect(part->pd2);
@@ -1785,6 +1787,8 @@ int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, i
                        
                        if (part->clumpcurve)
                                curvemapping_changed_all(part->clumpcurve);
+                       if (part->roughcurve)
+                               curvemapping_changed_all(part->roughcurve);
                        
                        par.co[0] = par.co[1] = par.co[2] = 0.0f;
                        copy_v3_v3(key.co, vec_to_point);
@@ -1991,6 +1995,8 @@ static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ParticleSi
        /* prepare curvemapping tables */
        if (part->clumpcurve)
                curvemapping_changed_all(part->clumpcurve);
+       if (part->roughcurve)
+               curvemapping_changed_all(part->roughcurve);
 
        return true;
 }
@@ -3166,6 +3172,18 @@ void BKE_particlesettings_clump_curve_init(ParticleSettings *part)
        part->clumpcurve = cumap;
 }
 
+void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
+{
+       CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+       
+       cumap->cm[0].curve[0].x = 0.0f;
+       cumap->cm[0].curve[0].y = 1.0f;
+       cumap->cm[0].curve[1].x = 1.0f;
+       cumap->cm[0].curve[1].y = 1.0f;
+       
+       part->roughcurve = cumap;
+}
+
 ParticleSettings *BKE_particlesettings_copy(ParticleSettings *part)
 {
        ParticleSettings *partn;
@@ -3179,6 +3197,8 @@ ParticleSettings *BKE_particlesettings_copy(ParticleSettings *part)
 
        if (part->clumpcurve)
                partn->clumpcurve = curvemapping_copy(part->clumpcurve);
+       if (part->roughcurve)
+               partn->roughcurve = curvemapping_copy(part->roughcurve);
        
        partn->boids = boid_copy_settings(part->boids);
 
index 68e11c9368ecfddc41eb325f2984622c2d70bf27..d797669901154aa6e8a7719521fdfa92ca682cff 100644 (file)
@@ -413,7 +413,7 @@ static void do_rough(const float loc[3], float mat[4][4], float t, float fac, fl
        madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
 }
 
-static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float shape, ParticleKey *state)
+static void do_rough_end(const float loc[3], float mat[4][4], float t, float fac, float shape, ParticleKey *state)
 {
        float rough[2];
        float roughfac;
@@ -428,6 +428,27 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float
        madd_v3_v3fl(state->co, mat[1], rough[1]);
 }
 
+static void do_rough_curve(const float loc[3], float mat[4][4], float time, float fac, float size, CurveMapping *roughcurve, ParticleKey *state)
+{
+       float rough[3];
+       float rco[3];
+       
+       if (!roughcurve)
+               return;
+       
+       fac *= CLAMPIS(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
+       
+       copy_v3_v3(rco, loc);
+       mul_v3_fl(rco, time);
+       rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
+       rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
+       rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
+       
+       madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
+       madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
+       madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
+}
+
 void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t)
 {
        ParticleSettings *part = sim->psys->part;
@@ -462,18 +483,23 @@ void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, Part
                }
        }
 
-       if (rough1 > 0.f)
-               do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
-
-       if (rough2 > 0.f) {
-               float vec[3];
-               psys_frand_vec(sim->psys, i + 27, vec);
-               do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
+       if (part->roughcurve) {
+               do_rough_curve(orco, mat, t, rough1, part->rough1_size, part->roughcurve, state);
        }
-
-       if (rough_end > 0.f) {
-               float vec[3];
-               psys_frand_vec(sim->psys, i + 27, vec);
-               do_rough_end(vec, mat, t, rough_end, part->rough_end_shape, state);
+       else {
+               if (rough1 > 0.f)
+                       do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
+       
+               if (rough2 > 0.f) {
+                       float vec[3];
+                       psys_frand_vec(sim->psys, i + 27, vec);
+                       do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
+               }
+       
+               if (rough_end > 0.f) {
+                       float vec[3];
+                       psys_frand_vec(sim->psys, i + 27, vec);
+                       do_rough_end(vec, mat, t, rough_end, part->rough_end_shape, state);
+               }
        }
 }
index 10bdfbd70e7b94cb2fa5106e6745b789eebb13dd..be1311249ee565153097e45663e07eb033673fa3 100644 (file)
@@ -3819,6 +3819,9 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
        part->clumpcurve = newdataadr(fd, part->clumpcurve);
        if (part->clumpcurve)
                direct_link_curvemapping(fd, part->clumpcurve);
+       part->roughcurve = newdataadr(fd, part->roughcurve);
+       if (part->roughcurve)
+               direct_link_curvemapping(fd, part->roughcurve);
 
        part->effector_weights = newdataadr(fd, part->effector_weights);
        if (!part->effector_weights)
index 81f4c16cea14dae517ff7e5255ff9533166945cf..1de2b6b267a22b40514d81aec2dce4966329b5da 100644 (file)
@@ -1110,6 +1110,8 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
 
                        if (part->clumpcurve)
                                write_curvemapping(wd, part->clumpcurve);
+                       if (part->roughcurve)
+                               write_curvemapping(wd, part->roughcurve);
                        
                        dw = part->dupliweights.first;
                        for (; dw; dw=dw->next) {
index 6d119b039bd86b823806ffac018d6ad82b2a28d2..b5ba7fa1649a3630a3efc4bf98a0a717bf7661fd 100644 (file)
@@ -234,6 +234,7 @@ typedef struct ParticleSettings {
        /* keyed particles */
        int keyed_loops;
        struct CurveMapping *clumpcurve;
+       struct CurveMapping *roughcurve;
 
        /* hair dynamics */
        float bending_random;
index 6540604199d1b3bc1af742525058aac54942d998..8a9be88b3b15d8fc91606fe055dc86f28801eb5f 100644 (file)
@@ -898,6 +898,29 @@ void rna_ParticleSettings_use_clump_curve_set(PointerRNA *ptr, int value)
        }
 }
 
+int rna_ParticleSettings_use_roughness_curve_get(PointerRNA *ptr)
+{
+       ParticleSettings *part = ptr->data;
+       return part->roughcurve != NULL;
+}
+
+void rna_ParticleSettings_use_roughness_curve_set(PointerRNA *ptr, int value)
+{
+       ParticleSettings *part = ptr->data;
+       
+       if (!value) {
+               if (part->roughcurve) {
+                       curvemapping_free(part->roughcurve);
+                       part->roughcurve = NULL;
+               }
+       }
+       else {
+               if (!part->roughcurve) {
+                       BKE_particlesettings_rough_curve_init(part);
+               }
+       }
+}
+
 static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value)
 {
        Object *ob = ptr->id.data;
@@ -2912,6 +2935,18 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Shape", "Shape of end point rough");
        RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
 
+       prop = RNA_def_property(srna, "use_roughness_curve", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_funcs(prop, "rna_ParticleSettings_use_roughness_curve_get", "rna_ParticleSettings_use_roughness_curve_set");
+       RNA_def_property_ui_text(prop, "Use Roughness Curve", "Use a curve to define roughness");
+       RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
+       prop = RNA_def_property(srna, "roughness_curve", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "roughcurve");
+       RNA_def_property_struct_type(prop, "CurveMapping");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Roughness Curve", "Curve defining roughness");
+       RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
+
        prop = RNA_def_property(srna, "child_length", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "clength");
        RNA_def_property_range(prop, 0.0f, 1.0f);