Fluidsim - Restoring simulation speed control (ZanQdo request)

This commit restores support for freezing or speeding up physics sims. Animate
the "Speed" parameter under Domain->Time, which controls a multiplier factor for
the rate at which the sim proceeds (i.e. the old "Fac-Tim" setting).

Notes:
* Subversion bumped to 4 to patch up defaults for new value so that old sim
files will still run correctly
* Names/descriptions could do with some tweaking
* Porting this across was not that obvious since quite a bit of stuff had
changed (as in, been cleaned up). However, from tests so far, it seems to work
well.
This commit is contained in:
Joshua Leung 2012-01-22 03:42:49 +00:00
parent b1667911ef
commit cfab40b652
7 changed files with 63 additions and 43 deletions

@ -79,6 +79,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
sub = col.column(align=True) sub = col.column(align=True)
sub.prop(fluid, "start_time", text="Start") sub.prop(fluid, "start_time", text="Start")
sub.prop(fluid, "end_time", text="End") sub.prop(fluid, "end_time", text="End")
col.prop(fluid, "simulation_rate", text="Speed")
col = split.column() col = split.column()
col.label() col.label()
@ -230,6 +231,10 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
if fluid.viscosity_preset == 'MANUAL': if fluid.viscosity_preset == 'MANUAL':
sub.prop(fluid, "viscosity_base", text="Base") sub.prop(fluid, "viscosity_base", text="Base")
sub.prop(fluid, "viscosity_exponent", text="Exponent", slider=True) sub.prop(fluid, "viscosity_exponent", text="Exponent", slider=True)
else:
# just for padding to prevent jumping around
sub.separator()
sub.separator()
col.label(text="Optimization:") col.label(text="Optimization:")
col.prop(fluid, "grid_levels", slider=True) col.prop(fluid, "grid_levels", slider=True)

@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines. * and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */ * Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 261 #define BLENDER_VERSION 261
#define BLENDER_SUBVERSION 3 #define BLENDER_SUBVERSION 4
#define BLENDER_MINVERSION 250 #define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0 #define BLENDER_MINSUBVERSION 0

@ -13019,6 +13019,23 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
} }
} }
if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 4))
{
{
/* set fluidsim rate */
Object *ob;
for (ob = main->object.first; ob; ob = ob->id.next) {
ModifierData *md;
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Fluidsim) {
FluidsimSettings *fss = (FluidsimSettings *)md;
fss->animRate = 1.0f;
}
}
}
}
}
/* put compatibility code here until next subversion bump */ /* put compatibility code here until next subversion bump */
{ {
} }

@ -113,6 +113,18 @@ static float get_fluid_viscosity(FluidsimSettings *settings)
} }
} }
static float get_fluid_rate(FluidsimSettings *settings)
{
float rate = 1.0f; /* default rate if not animated... */
rate = settings->animRate;
if (rate < 0.0f)
rate = 0.0f;
return rate;
}
static void get_fluid_gravity(float *gravity, Scene *scene, FluidsimSettings *fss) static void get_fluid_gravity(float *gravity, Scene *scene, FluidsimSettings *fss)
{ {
if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
@ -305,6 +317,8 @@ static void free_domain_channels(FluidAnimChannels *channels)
channels->DomainGravity = NULL; channels->DomainGravity = NULL;
MEM_freeN(channels->DomainViscosity); MEM_freeN(channels->DomainViscosity);
channels->DomainViscosity = NULL; channels->DomainViscosity = NULL;
MEM_freeN(channels->DomainTime);
channels->DomainTime = NULL;
} }
static void free_all_fluidobject_channels(ListBase *fobjects) static void free_all_fluidobject_channels(ListBase *fobjects)
@ -351,14 +365,13 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
int length = channels->length; int length = channels->length;
float eval_time; float eval_time;
/* XXX: first init time channel - temporary for now */ /* init time values (assuming that time moves at a constant speed; may be overridden later) */
/* init time values (should be done after evaluating animated time curve) */
init_time(domainSettings, channels); init_time(domainSettings, channels);
/* allocate domain animation channels */ /* allocate domain animation channels */
channels->DomainGravity = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity"); channels->DomainGravity = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity");
channels->DomainViscosity = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity"); channels->DomainViscosity = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity");
//channels->DomainTime = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime"); channels->DomainTime = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime");
/* allocate fluid objects */ /* allocate fluid objects */
for (base=scene->base.first; base; base= base->next) { for (base=scene->base.first; base; base= base->next) {
@ -406,10 +419,9 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
for (i=0; i<channels->length; i++) { for (i=0; i<channels->length; i++) {
FluidObject *fobj; FluidObject *fobj;
float viscosity, gravity[3]; float viscosity, gravity[3];
float timeAtFrame; float timeAtFrame, time;
eval_time = domainSettings->bakeStart + i; eval_time = domainSettings->bakeStart + i;
timeAtFrame = channels->timeAtFrame[i+1];
/* XXX: This can't be used due to an anim sys optimisation that ignores recalc object animation, /* XXX: This can't be used due to an anim sys optimisation that ignores recalc object animation,
* leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ ) * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
@ -425,12 +437,24 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
/* now scene data should be current according to animation system, so we fill the channels */ /* now scene data should be current according to animation system, so we fill the channels */
/* Domain properties - gravity/viscosity/time */ /* Domain time */
// TODO: have option for not running sim, time mangling, in which case second case comes in handy
if (channels->DomainTime) {
time = get_fluid_rate(domainSettings) * channels->aniFrameTime;
timeAtFrame = channels->timeAtFrame[i] + time;
channels->timeAtFrame[i+1] = timeAtFrame;
set_channel(channels->DomainTime, i, &time, i, CHANNEL_FLOAT);
}
else {
timeAtFrame = channels->timeAtFrame[i+1];
}
/* Domain properties - gravity/viscosity */
get_fluid_gravity(gravity, scene, domainSettings); get_fluid_gravity(gravity, scene, domainSettings);
set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC); set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC);
viscosity = get_fluid_viscosity(domainSettings); viscosity = get_fluid_viscosity(domainSettings);
set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT); set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT);
// XXX : set_channel(channels->DomainTime, timeAtFrame, &time, i, CHANNEL_VEC);
/* object movement */ /* object movement */
for (fobj=fobjects->first; fobj; fobj=fobj->next) { for (fobj=fobjects->first; fobj; fobj=fobj->next) {
@ -958,38 +982,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
scene->r.cfra = origFrame; scene->r.cfra = origFrame;
ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1); ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
/* ---- XXX: No Time animation curve for now, leaving this code here for reference
{ int timeIcu[1] = { FLUIDSIM_TIME };
float timeDef[1] = { 1. };
// time channel is a bit special, init by hand...
timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex");
for(i=0; i<=scene->r.efra; i++) {
timeAtIndex[i] = (float)(i-startFrame);
}
fluidsimInitChannel(scene, &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
// time channel is a multiplicator for
if(channelDomainTime) {
for(i=0; i<allchannelSize; i++) {
channelDomainTime[i*2+0] = aniFrameTime * channelDomainTime[i*2+0];
if(channelDomainTime[i*2+0]<0.) channelDomainTime[i*2+0] = 0.;
}
}
timeAtFrame = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatframe");
timeAtFrame[0] = timeAtFrame[1] = domainSettings->animStart; // start at index 1
if(channelDomainTime) {
for(i=2; i<=allchannelSize; i++) {
timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0];
}
fsset->} else {
for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; }
}
} // domain channel init
*/
/* ******** init domain object's matrix ******** */ /* ******** init domain object's matrix ******** */
copy_m4_m4(domainMat, fsDomain->obmat); copy_m4_m4(domainMat, fsDomain->obmat);
if(!invert_m4_m4(invDomMat, domainMat)) { if(!invert_m4_m4(invDomMat, domainMat)) {

@ -140,8 +140,8 @@ typedef struct FluidsimSettings {
int lastgoodframe; int lastgoodframe;
int pad; /* Simulation/flow rate control (i.e. old "Fac-Time") */
float animRate;
} FluidsimSettings; } FluidsimSettings;
/* ob->fluidsimSettings defines */ /* ob->fluidsimSettings defines */

@ -340,6 +340,11 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna)
RNA_def_property_range(prop, 0.001, 10); RNA_def_property_range(prop, 0.001, 10);
RNA_def_property_ui_text(prop, "Real World Size", "Size of the simulation domain in metres"); RNA_def_property_ui_text(prop, "Real World Size", "Size of the simulation domain in metres");
prop= RNA_def_property(srna, "simulation_rate", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "animRate");
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Simulation Speed", "Fluid motion rate (0 = stationary, 1 = normal speed)");
prop= RNA_def_property(srna, "viscosity_preset", PROP_ENUM, PROP_NONE); prop= RNA_def_property(srna, "viscosity_preset", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "viscosityMode"); RNA_def_property_enum_sdna(prop, NULL, "viscosityMode");
RNA_def_property_enum_items(prop, viscosity_items); RNA_def_property_enum_items(prop, viscosity_items);

@ -95,6 +95,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd)
fss->animStart = 0.0; fss->animStart = 0.0;
fss->animEnd = 4.0; fss->animEnd = 4.0;
fss->animRate = 1.0;
fss->gstar = 0.005; // used as normgstar fss->gstar = 0.005; // used as normgstar
fss->maxRefine = -1; fss->maxRefine = -1;
// maxRefine is set according to resolutionxyz during bake // maxRefine is set according to resolutionxyz during bake