Fluid: Bounding boxes for effector objects

This commit adds bounding box support for emission objects - similarly to flow objects. Before, each effector object had to iterate over the entire domain. Bake times of scenes with multiple obstacles improved significantly with this optimization.

Other improvements that were implemented alongside the bbox feature:
- Option for subframe sampling for effector objects
- Option to enable / disable effectors (can be animated)
- Optimization for static objects. If a flow or effector object does not move and the adaptive domain is not in use, the bake time will be optimized further by reusing the flow / effector grids from the previous frame (no recalculation).
This commit is contained in:
Sebastián Barschkis 2020-03-04 18:44:23 +01:00
parent 3c74d45c9e
commit a5c4a44df6
Notes: blender-bot 2023-02-14 11:34:30 +01:00
Referenced by commit e65f5c07b0, Fluid: Added missing UI options for effector objects
Referenced by commit 4ccbbd3080, Fix T74446: Liquid Inflow Does Not Work
Referenced by issue #88566, Mantaflow inflow with shapekeys is not working anymore (regression)
Referenced by issue #74446, Liquid Inflow Does Not Work
10 changed files with 846 additions and 437 deletions

View File

@ -93,7 +93,9 @@ int manta_get_res_x(struct MANTA *fluid);
int manta_get_res_y(struct MANTA *fluid);
int manta_get_res_z(struct MANTA *fluid);
float *manta_get_phi_in(struct MANTA *fluid);
float *manta_get_phistatic_in(struct MANTA *fluid);
float *manta_get_phiobs_in(struct MANTA *fluid);
float *manta_get_phiobsstatic_in(struct MANTA *fluid);
float *manta_get_phiout_in(struct MANTA *fluid);
/* Smoke functions */

View File

@ -130,6 +130,7 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
// Fluid low res grids
mPhiIn = nullptr;
mPhiStaticIn = nullptr;
mPhiOutIn = nullptr;
mPhi = nullptr;
@ -140,6 +141,7 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
// Fluid obstacle
mPhiObsIn = nullptr;
mPhiObsStaticIn = nullptr;
mNumObstacle = nullptr;
mObVelocityX = nullptr;
mObVelocityY = nullptr;
@ -3007,6 +3009,7 @@ void MANTA::updatePointers()
mFlags = (int *)pyObjectToPointer(callPythonFunction("flags" + solver_ext, func));
mPhiIn = (float *)pyObjectToPointer(callPythonFunction("phiIn" + solver_ext, func));
mPhiStaticIn = (float *)pyObjectToPointer(callPythonFunction("phiSIn" + solver_ext, func));
mVelocityX = (float *)pyObjectToPointer(callPythonFunction("x_vel" + solver_ext, func));
mVelocityY = (float *)pyObjectToPointer(callPythonFunction("y_vel" + solver_ext, func));
mVelocityZ = (float *)pyObjectToPointer(callPythonFunction("z_vel" + solver_ext, func));
@ -3019,6 +3022,8 @@ void MANTA::updatePointers()
}
if (mUsingObstacle) {
mPhiObsIn = (float *)pyObjectToPointer(callPythonFunction("phiObsIn" + solver_ext, func));
mPhiObsStaticIn = (float *)pyObjectToPointer(
callPythonFunction("phiObsSIn" + solver_ext, func));
mObVelocityX = (float *)pyObjectToPointer(callPythonFunction("x_obvel" + solver_ext, func));
mObVelocityY = (float *)pyObjectToPointer(callPythonFunction("y_obvel" + solver_ext, func));
mObVelocityZ = (float *)pyObjectToPointer(callPythonFunction("z_obvel" + solver_ext, func));

View File

@ -376,10 +376,18 @@ struct MANTA {
{
return mPhiIn;
}
inline float *getPhiStaticIn()
{
return mPhiStaticIn;
}
inline float *getPhiObsIn()
{
return mPhiObsIn;
}
inline float *getPhiObsStaticIn()
{
return mPhiObsStaticIn;
}
inline float *getPhiGuideIn()
{
return mPhiGuideIn;
@ -823,7 +831,9 @@ struct MANTA {
// Liquid grids
float *mPhiIn;
float *mPhiStaticIn;
float *mPhiObsIn;
float *mPhiObsStaticIn;
float *mPhiGuideIn;
float *mPhiOutIn;
float *mPhi;

View File

@ -332,10 +332,18 @@ float *manta_get_phi_in(MANTA *fluid)
{
return fluid->getPhiIn();
}
float *manta_get_phistatic_in(MANTA *fluid)
{
return fluid->getPhiStaticIn();
}
float *manta_get_phiobs_in(MANTA *fluid)
{
return fluid->getPhiObsIn();
}
float *manta_get_phiobsstatic_in(MANTA *fluid)
{
return fluid->getPhiObsStaticIn();
}
float *manta_get_phiout_in(MANTA *fluid)
{
return fluid->getPhiOutIn();

View File

@ -230,6 +230,7 @@ y_vel_s$ID$ = s$ID$.create(RealGrid)\n\
z_vel_s$ID$ = s$ID$.create(RealGrid)\n\
pressure_s$ID$ = s$ID$.create(RealGrid)\n\
phiObs_s$ID$ = s$ID$.create(LevelsetGrid)\n\
phiSIn_s$ID$ = s$ID$.create(LevelsetGrid) # helper for static flow objects\n\
phiIn_s$ID$ = s$ID$.create(LevelsetGrid)\n\
phiOut_s$ID$ = s$ID$.create(LevelsetGrid)\n\
forces_s$ID$ = s$ID$.create(Vec3Grid)\n\
@ -252,6 +253,7 @@ const std::string fluid_alloc_obstacle =
"\n\
mantaMsg('Allocating obstacle data')\n\
numObs_s$ID$ = s$ID$.create(RealGrid)\n\
phiObsSIn_s$ID$ = s$ID$.create(LevelsetGrid) # helper for static obstacles\n\
phiObsIn_s$ID$ = s$ID$.create(LevelsetGrid)\n\
obvel_s$ID$ = s$ID$.create(MACGrid)\n\
obvelC_s$ID$ = s$ID$.create(Vec3Grid)\n\

View File

@ -174,6 +174,7 @@ def liquid_adaptive_step_$ID$(framenr):\n\
\n\
if using_obstacle_s$ID$:\n\
mantaMsg('Initializing obstacle levelset')\n\
phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\

View File

@ -277,6 +277,7 @@ def smoke_adaptive_step_$ID$(framenr):\n\
\n\
if using_obstacle_s$ID$:\n\
mantaMsg('Initializing obstacle levelset')\n\
phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\

File diff suppressed because it is too large Load Diff

View File

@ -564,6 +564,14 @@ enum {
FLUID_EFFECTOR_GUIDE_AVERAGED = 3,
};
/* Effector flags. */
enum {
/* Control when to apply inflow. */
FLUID_EFFECTOR_USE_EFFEC = (1 << 1),
/* Control how to initialize flow objects. */
FLUID_EFFECTOR_USE_PLANE_INIT = (1 << 2),
};
/* Collision objects (filled with smoke). */
typedef struct FluidEffectorSettings {
@ -579,8 +587,9 @@ typedef struct FluidEffectorSettings {
float surface_distance; /* Thickness of mesh surface, used in obstacle sdf. */
int flags;
int subframes;
short type;
char _pad1[2];
char _pad1[6];
/* Guiding options. */
float vel_multi; /* Multiplier for object velocity. */

View File

@ -2243,7 +2243,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem flow_types[] = {
static const EnumPropertyItem flow_type_items[] = {
{FLUID_FLOW_TYPE_SMOKE, "SMOKE", 0, "Smoke", "Add smoke"},
{FLUID_FLOW_TYPE_SMOKEFIRE, "BOTH", 0, "Fire + Smoke", "Add fire and smoke"},
{FLUID_FLOW_TYPE_FIRE, "FIRE", 0, "Fire", "Add fire"},
@ -2251,7 +2251,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem flow_behaviors[] = {
static EnumPropertyItem flow_behavior_items[] = {
{FLUID_FLOW_BEHAVIOR_INFLOW, "INFLOW", 0, "Inflow", "Add fluid to simulation"},
{FLUID_FLOW_BEHAVIOR_OUTFLOW, "OUTFLOW", 0, "Outflow", "Delete fluid from simulation"},
{FLUID_FLOW_BEHAVIOR_GEOMETRY,
@ -2318,14 +2318,14 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "flow_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, flow_types);
RNA_def_property_enum_items(prop, flow_type_items);
RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_flowtype_set", NULL);
RNA_def_property_ui_text(prop, "Flow Type", "Change type of fluid in the simulation");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
prop = RNA_def_property(srna, "flow_behavior", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "behavior");
RNA_def_property_enum_items(prop, flow_behaviors);
RNA_def_property_enum_items(prop, flow_behavior_items);
RNA_def_property_ui_text(prop, "Flow Behavior", "Change flow behavior in the simulation");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
@ -2535,7 +2535,7 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
prop = RNA_def_property(srna, "use_plane_init", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_PLANE_INIT);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_EFFECTOR_USE_PLANE_INIT);
RNA_def_property_ui_text(prop, "Is Planar", "Treat this object as a planar, unclosed mesh");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
@ -2555,6 +2555,20 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna)
RNA_def_property_enum_items(prop, fluid_guide_mode_items);
RNA_def_property_ui_text(prop, "Guiding mode", "How to create guiding velocities");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update");
prop = RNA_def_property(srna, "use_effector", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_EFFECTOR_USE_EFFEC);
RNA_def_property_ui_text(prop, "Enabled", "Control when to apply the effector");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
prop = RNA_def_property(srna, "subframes", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 200);
RNA_def_property_ui_range(prop, 0, 10, 1, -1);
RNA_def_property_ui_text(prop,
"Subframes",
"Number of additional samples to take between frames to improve "
"quality of fast moving effector objects");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
}
void RNA_def_fluid(BlenderRNA *brna)