Cloth Simulation: add time scale property
authorCampbell Barton <ideasman42@gmail.com>
Sat, 30 Jul 2016 04:46:19 +0000 (14:46 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 30 Jul 2016 05:14:26 +0000 (15:14 +1000)
This setting can also be animated, to create a "time warp" effect.

D2122 by @LucaRood

release/scripts/startup/bl_ui/properties_physics_cloth.py
source/blender/blenkernel/intern/cloth.c
source/blender/blenloader/intern/versioning_270.c
source/blender/makesdna/DNA_cloth_types.h
source/blender/makesrna/intern/rna_cloth.c
source/blender/physics/intern/BPH_mass_spring.cpp

index d3b2a9fd1490610e4dd0945d9c7723265b89c0df..3ebf2691b4c6c41935b37363d64ec8b8d795d185 100644 (file)
@@ -75,6 +75,11 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
         split.label(text="Quality:")
         split.prop(cloth, "quality", text="Steps")
 
+        split = layout.split(percentage=0.25)
+
+        split.label(text="Speed:")
+        split.prop(cloth, "time_scale", text="Multiplier")
+
         split = layout.split()
 
         col = split.column()
index 22d7cbafe419f5a3dbf58661760ed1d6c5995dd2..681b93172b238567fc4d275cee3a89145a97329b 100644 (file)
@@ -97,6 +97,7 @@ void cloth_init(ClothModifierData *clmd )
        clmd->sim_parms->avg_spring_len = 0.0;
        clmd->sim_parms->presets = 2; /* cotton as start setting */
        clmd->sim_parms->timescale = 1.0f; /* speed factor, describes how fast cloth moves */
+       clmd->sim_parms->time_scale = 1.0f; /* multiplies cloth speed */
        clmd->sim_parms->reset = 0;
        clmd->sim_parms->vel_damping = 1.0f; /* 1.0 = no damping, 0.0 = fully dampened */
        
@@ -411,7 +412,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
 
        BKE_ptcache_id_from_cloth(&pid, ob, clmd);
        BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
-       clmd->sim_parms->timescale= timescale;
+       clmd->sim_parms->timescale= timescale * clmd->sim_parms->time_scale;
 
        if (clmd->sim_parms->reset || (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->mvert_num)) {
                clmd->sim_parms->reset = 0;
index a254a854c66370f33e9ca1ae3064928e00408655..3e6b0d34ba68b5031906c21d63751b85fb3bcbeb 100644 (file)
@@ -1231,5 +1231,24 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                                br->flag |= BRUSH_ACCUMULATE;
                        }
                }
+
+               if (!DNA_struct_elem_find(fd->filesdna, "ClothSimSettings", "float", "time_scale")) {
+                       Object *ob;
+                       ModifierData *md;
+                       for (ob = main->object.first; ob; ob = ob->id.next) {
+                               for (md = ob->modifiers.first; md; md = md->next) {
+                                       if (md->type == eModifierType_Cloth) {
+                                               ClothModifierData *clmd = (ClothModifierData *)md;
+                                               clmd->sim_parms->time_scale = 1.0f;
+                                       }
+                                       else if (md->type == eModifierType_ParticleSystem) {
+                                               ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
+                                               if (pmd->psys->clmd) {
+                                                       pmd->psys->clmd->sim_parms->time_scale = 1.0f;
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
 }
index d385e303a7c2f7baa8a64dfc3ded7e1b813b51a0..ee147da8dae173e2ff799ef58c83c7292fb4fac6 100644 (file)
@@ -63,6 +63,7 @@ typedef struct ClothSimSettings {
        float   max_sewing;     /* max sewing force */
        float   avg_spring_len; /* used for normalized springs */
        float   timescale; /* parameter how fast cloth runs */
+       float   time_scale; /* multiplies cloth speed */
        float   maxgoal;        /* see SB */
        float   eff_force_scale;/* Scaling of effector forces (see softbody_calc_forces).*/
        float   eff_wind_scale; /* Scaling of effector wind (see softbody_calc_forces). */
@@ -98,6 +99,7 @@ typedef struct ClothSimSettings {
        short   presets; /* used for presets on GUI */
        short   reset;
 
+       char pad0[4];
        struct EffectorWeights *effector_weights;
 } ClothSimSettings;
 
index 41c08250f0ecfab8581bd406bcbef957f02a3f94..781e44c9ed687697c12800b5916a921cb4483067 100644 (file)
@@ -442,6 +442,13 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
                                 "Quality of the simulation in steps per frame (higher is better quality but slower)");
        RNA_def_property_update(prop, 0, "rna_cloth_update");
 
+       prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "time_scale");
+       RNA_def_property_range(prop, 0.0f, FLT_MAX);
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 10, 3);
+       RNA_def_property_ui_text(prop, "Speed", "Cloth speed is multiplied by this value");
+       RNA_def_property_update(prop, 0, "rna_cloth_update");
+
        prop = RNA_def_property(srna, "vertex_group_shrink", PROP_STRING, PROP_NONE);
        RNA_def_property_string_funcs(prop, "rna_ClothSettings_shrink_vgroup_get", "rna_ClothSettings_shrink_vgroup_length",
                                      "rna_ClothSettings_shrink_vgroup_set");
index 648ef1326558730c4738e04f2cfade13948bc960..359395b63c453ca331c58963afbaecd864bb93df 100644 (file)
@@ -376,7 +376,8 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
                s->flags |= CLOTH_SPRING_FLAG_NEEDED;
                
                // current_position = xold + t * (newposition - xold)
-               interp_v3_v3v3(goal_x, verts[s->ij].xold, verts[s->ij].xconst, time);
+               /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */
+               interp_v3_v3v3(goal_x, verts[s->ij].xold, verts[s->ij].xconst, time / parms->time_scale);
                sub_v3_v3v3(goal_v, verts[s->ij].xconst, verts[s->ij].xold); // distance covered over dt==1
                
                scaling = parms->goalspring + s->stiffness * fabsf(parms->max_struct - parms->goalspring);
@@ -1004,6 +1005,8 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
                                float v[3];
                                sub_v3_v3v3(v, verts[i].xconst, verts[i].xold);
                                // mul_v3_fl(v, clmd->sim_parms->stepsPerFrame);
+                               /* divide by time_scale to prevent constrained velocities from being multiplied */
+                               mul_v3_fl(v, 1.0f / clmd->sim_parms->time_scale);
                                BPH_mass_spring_set_velocity(id, i, v);
                        }
                }
@@ -1070,7 +1073,8 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
                        if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) {
                                if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
                                        float x[3];
-                                       interp_v3_v3v3(x, verts[i].xold, verts[i].xconst, step + dt);
+                                       /* divide by time_scale to prevent pinned vertices' delta locations from being multiplied */
+                                       interp_v3_v3v3(x, verts[i].xold, verts[i].xconst, (step + dt) / clmd->sim_parms->time_scale);
                                        BPH_mass_spring_set_position(id, i, x);
                                }
                        }