Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastián Barschkis <sebbas@sebbas.org>2021-08-09 12:19:42 +0300
committerSebastián Barschkis <sebbas@sebbas.org>2021-08-09 12:19:42 +0300
commit4e84e076b2567ee2ec9fc70aced35a3ebd0ad19e (patch)
treebd81f667cd713eca1c812dd79750820eed943026
parent23d5bbd104581550f84c690a42e36ddbea070e21 (diff)
Fluid: Initial support for 2D fluid simulationsfluid-mantaflow-2d
Initial adjustments for 2D (real-time) simulations. Basic functionality includes: - 2D/3D switcher in domain settings - 2D simulation support for smoke/fire, wavelet noise, liquid particles, secondary particles - UI switcher to choose the axis that will be simulated on - Planar visualization in workbench render Some things that remain to do (non-exhaustive list): - Eevee & Cycles support - Liquid meshing - Liquid viscosity solver
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp34
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h31
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py6
-rw-r--r--source/blender/blenkernel/BKE_fluid.h3
-rw-r--r--source/blender/blenkernel/intern/fluid.c73
-rw-r--r--source/blender/blenkernel/intern/particle_system.c30
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c11
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c3
-rw-r--r--source/blender/makesdna/DNA_fluid_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c90
10 files changed, 233 insertions, 54 deletions
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index 6c8e45ceeb4..86f6d7f6ab1 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -204,6 +204,14 @@ MANTA::MANTA(int *res, FluidModifierData *fmd)
mResXParticle = mUpresParticle * mResX;
mResYParticle = mUpresParticle * mResY;
mResZParticle = mUpresParticle * mResZ;
+ if (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D) {
+ if (fds->slice_axis == SLICE_AXIS_X)
+ mResXParticle = 1;
+ else if (fds->slice_axis == SLICE_AXIS_Y)
+ mResYParticle = 1;
+ else if (fds->slice_axis == SLICE_AXIS_Z)
+ mResZParticle = 1;
+ }
mTotalCellsParticles = mResXParticle * mResYParticle * mResZParticle;
initSuccess &= initSndParts();
@@ -266,6 +274,14 @@ MANTA::MANTA(int *res, FluidModifierData *fmd)
mResXNoise = amplify * mResX;
mResYNoise = amplify * mResY;
mResZNoise = amplify * mResZ;
+ if (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D) {
+ if (fds->slice_axis == SLICE_AXIS_X)
+ mResXNoise = 1;
+ else if (fds->slice_axis == SLICE_AXIS_Y)
+ mResYNoise = 1;
+ else if (fds->slice_axis == SLICE_AXIS_Z)
+ mResZNoise = 1;
+ }
mTotalCellsHigh = mResXNoise * mResYNoise * mResZNoise;
/* Initialize Mantaflow variables in Python. */
@@ -785,8 +801,10 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
mRNAMap["BOUND_CONDITIONS"] = borderCollisions;
mRNAMap["BOUNDARY_WIDTH"] = to_string(fds->boundary_width);
mRNAMap["RES"] = to_string(mMaxRes);
- mRNAMap["RESX"] = to_string(mResX);
- mRNAMap["RESY"] = (is2D) ? to_string(mResZ) : to_string(mResY);
+ mRNAMap["RESX"] = (is2D && fds->slice_axis == SLICE_AXIS_X) ? to_string(mResY) :
+ to_string(mResX);
+ mRNAMap["RESY"] = (is2D && fds->slice_axis != SLICE_AXIS_Z) ? to_string(mResZ) :
+ to_string(mResY);
mRNAMap["RESZ"] = (is2D) ? to_string(1) : to_string(mResZ);
mRNAMap["TIME_SCALE"] = to_string(fds->time_scale);
mRNAMap["FRAME_LENGTH"] = to_string(fds->frame_length);
@@ -801,14 +819,18 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
mRNAMap["NOISE_SCALE"] = to_string(fds->noise_scale);
mRNAMap["MESH_SCALE"] = to_string(fds->mesh_scale);
mRNAMap["PARTICLE_SCALE"] = to_string(fds->particle_scale);
- mRNAMap["NOISE_RESX"] = to_string(mResXNoise);
- mRNAMap["NOISE_RESY"] = (is2D) ? to_string(mResZNoise) : to_string(mResYNoise);
+ mRNAMap["NOISE_RESX"] = (is2D && fds->slice_axis == SLICE_AXIS_X) ? to_string(mResYNoise) :
+ to_string(mResXNoise);
+ mRNAMap["NOISE_RESY"] = (is2D && fds->slice_axis != SLICE_AXIS_Z) ? to_string(mResZNoise) :
+ to_string(mResYNoise);
mRNAMap["NOISE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZNoise);
mRNAMap["MESH_RESX"] = to_string(mResXMesh);
mRNAMap["MESH_RESY"] = (is2D) ? to_string(mResZMesh) : to_string(mResYMesh);
mRNAMap["MESH_RESZ"] = (is2D) ? to_string(1) : to_string(mResZMesh);
- mRNAMap["PARTICLE_RESX"] = to_string(mResXParticle);
- mRNAMap["PARTICLE_RESY"] = (is2D) ? to_string(mResZParticle) : to_string(mResYParticle);
+ mRNAMap["PARTICLE_RESX"] = (is2D && fds->slice_axis == SLICE_AXIS_X) ? to_string(mResYParticle) :
+ to_string(mResXParticle);
+ mRNAMap["PARTICLE_RESY"] = (is2D && fds->slice_axis != SLICE_AXIS_Z) ? to_string(mResZParticle) :
+ to_string(mResYParticle);
mRNAMap["PARTICLE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZParticle);
mRNAMap["GUIDING_RESX"] = to_string(mResGuiding[0]);
mRNAMap["GUIDING_RESY"] = (is2D) ? to_string(mResGuiding[2]) : to_string(mResGuiding[1]);
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index 3bf8e66c110..8560f88e8e5 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -62,22 +62,22 @@ s$ID$ = Solver(name='solver_base$ID$', gridSize=gs_s$ID$, dim=dim_s$ID$)\n";
const std::string fluid_solver_noise =
"\n\
mantaMsg('Solver noise')\n\
-sn$ID$ = Solver(name='solver_noise$ID$', gridSize=gs_sn$ID$)\n";
+sn$ID$ = Solver(name='solver_noise$ID$', gridSize=gs_sn$ID$, dim=dim_s$ID$)\n";
const std::string fluid_solver_mesh =
"\n\
mantaMsg('Solver mesh')\n\
-sm$ID$ = Solver(name='solver_mesh$ID$', gridSize=gs_sm$ID$)\n";
+sm$ID$ = Solver(name='solver_mesh$ID$', gridSize=gs_sm$ID$, dim=dim_s$ID$)\n";
const std::string fluid_solver_particles =
"\n\
mantaMsg('Solver particles')\n\
-sp$ID$ = Solver(name='solver_particles$ID$', gridSize=gs_sp$ID$)\n";
+sp$ID$ = Solver(name='solver_particles$ID$', gridSize=gs_sp$ID$, dim=dim_s$ID$)\n";
const std::string fluid_solver_guiding =
"\n\
mantaMsg('Solver guiding')\n\
-sg$ID$ = Solver(name='solver_guiding$ID$', gridSize=gs_sg$ID$)\n";
+sg$ID$ = Solver(name='solver_guiding$ID$', gridSize=gs_sg$ID$, dim=dim_s$ID$)\n";
const std::string fluid_solver_viscosity =
"\n\
@@ -95,6 +95,11 @@ dim_s$ID$ = $SOLVER_DIM$\n\
res_s$ID$ = $RES$\n\
gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$) # in SI unit (e.g. m/s^2)\n\
gs_s$ID$ = vec3($RESX$, $RESY$, $RESZ$)\n\
+if dim_s$ID$ == 2:\n\
+ gs_s$ID$.z = 1\n\
+ gravity_s$ID$.y = gravity_s$ID$.z\n\
+ gravity_s$ID$.z = 0\n\
+\n\
maxVel_s$ID$ = 0\n\
\n\
domainClosed_s$ID$ = $DOMAIN_CLOSED$\n\
@@ -178,24 +183,32 @@ const std::string fluid_variables_noise =
"\n\
mantaMsg('Fluid variables noise')\n\
upres_sn$ID$ = $NOISE_SCALE$\n\
-gs_sn$ID$ = vec3(upres_sn$ID$*gs_s$ID$.x, upres_sn$ID$*gs_s$ID$.y, upres_sn$ID$*gs_s$ID$.z)\n";
+gs_sn$ID$ = vec3(upres_sn$ID$*gs_s$ID$.x, upres_sn$ID$*gs_s$ID$.y, upres_sn$ID$*gs_s$ID$.z)\n\
+if dim_s$ID$ == 2:\n\
+ gs_sn$ID$.z = 1\n";
const std::string fluid_variables_mesh =
"\n\
mantaMsg('Fluid variables mesh')\n\
upres_sm$ID$ = $MESH_SCALE$\n\
-gs_sm$ID$ = vec3(upres_sm$ID$*gs_s$ID$.x, upres_sm$ID$*gs_s$ID$.y, upres_sm$ID$*gs_s$ID$.z)\n";
+gs_sm$ID$ = vec3(upres_sm$ID$*gs_s$ID$.x, upres_sm$ID$*gs_s$ID$.y, upres_sm$ID$*gs_s$ID$.z)\n\
+if dim_s$ID$ == 2:\n\
+ gs_sm$ID$.z = 1\n";
const std::string fluid_variables_particles =
"\n\
mantaMsg('Fluid variables particles')\n\
upres_sp$ID$ = $PARTICLE_SCALE$\n\
-gs_sp$ID$ = vec3(upres_sp$ID$*gs_s$ID$.x, upres_sp$ID$*gs_s$ID$.y, upres_sp$ID$*gs_s$ID$.z)\n";
+gs_sp$ID$ = vec3(upres_sp$ID$*gs_s$ID$.x, upres_sp$ID$*gs_s$ID$.y, upres_sp$ID$*gs_s$ID$.z)\n\
+if dim_s$ID$ == 2:\n\
+ gs_sp$ID$.z = 1\n";
const std::string fluid_variables_guiding =
"\n\
mantaMsg('Fluid variables guiding')\n\
gs_sg$ID$ = vec3($GUIDING_RESX$, $GUIDING_RESY$, $GUIDING_RESZ$)\n\
+if dim_s$ID$ == 2:\n\
+ gs_sg$ID$.z = 1\n\
\n\
alpha_sg$ID$ = $GUIDING_ALPHA$\n\
beta_sg$ID$ = $GUIDING_BETA$\n\
@@ -206,7 +219,9 @@ theta_sg$ID$ = 1.0\n";
const std::string fluid_variables_viscosity =
"\n\
-gs_sv$ID$ = vec3($RESX$*2, $RESY$*2, $RESZ$*2)\n";
+gs_sv$ID$ = vec3($RESX$*2, $RESY$*2, $RESZ$*2)\n\
+if dim_s$ID$ == 2:\n\
+ gs_sv$ID$.z = 1\n";
const std::string fluid_with_obstacle =
"\n\
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 6408d4096fe..f2dd96c8ee0 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -197,6 +197,9 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
if PhysicButtonsPanel.poll_gas_domain(context):
col.prop(domain, "clipping", text="Empty Space")
col.prop(domain, "delete_in_obstacle", text="Delete in Obstacle")
+ col.prop(domain, "solver_res", text="Dimension")
+ if domain.solver_res == '2D':
+ col.prop(domain, "slice_axis", text="Axis")
if domain.cache_type == 'MODULAR':
col.separator()
@@ -1379,7 +1382,8 @@ class PHYSICS_PT_viewport_display_slicing(PhysicButtonsPanel, Panel):
layout.active = domain.use_slice
col = layout.column()
- col.prop(domain, "slice_axis")
+ if domain.solver_res == '3D':
+ col.prop(domain, "slice_axis")
col.prop(domain, "slice_depth")
sub = col.column()
diff --git a/source/blender/blenkernel/BKE_fluid.h b/source/blender/blenkernel/BKE_fluid.h
index 33ff6943514..9fbe9e590b0 100644
--- a/source/blender/blenkernel/BKE_fluid.h
+++ b/source/blender/blenkernel/BKE_fluid.h
@@ -89,6 +89,9 @@ void BKE_fluid_particles_set(struct FluidDomainSettings *settings, int value, bo
void BKE_fluid_domain_type_set(struct Object *object,
struct FluidDomainSettings *settings,
int type);
+void BKE_fluid_domain_solver_res_set(struct Object *object,
+ struct FluidDomainSettings *settings,
+ int type);
void BKE_fluid_flow_type_set(struct Object *object, struct FluidFlowSettings *settings, int type);
void BKE_fluid_effector_type_set(struct Object *object,
struct FluidEffectorSettings *settings,
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index ce7832dbffd..93d45d7b92c 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -141,7 +141,10 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds,
int n_shift[3])
{
struct MANTA *fluid_old = fds->fluid;
- const int block_size = fds->noise_scale;
+ int block_size[3] = {fds->noise_scale, fds->noise_scale, fds->noise_scale};
+ if (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D) {
+ block_size[fds->slice_axis - 1] = 1;
+ }
int new_shift[3] = {0};
sub_v3_v3v3_int(new_shift, n_shift, o_shift);
@@ -254,13 +257,13 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds,
if (fds->flags & FLUID_DOMAIN_USE_NOISE) {
int i, j, k;
/* old grid index */
- int xx_o = xo * block_size;
- int yy_o = yo * block_size;
- int zz_o = zo * block_size;
+ int xx_o = xo * block_size[0];
+ int yy_o = yo * block_size[1];
+ int zz_o = zo * block_size[2];
/* new grid index */
- int xx_n = xn * block_size;
- int yy_n = yn * block_size;
- int zz_n = zn * block_size;
+ int xx_n = xn * block_size[0];
+ int yy_n = yn * block_size[1];
+ int zz_n = zn * block_size[2];
/* insert old texture values into new texture grids */
n_wt_tcu[index_new] = o_wt_tcu[index_old];
@@ -271,9 +274,9 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds,
n_wt_tcv2[index_new] = o_wt_tcv2[index_old];
n_wt_tcw2[index_new] = o_wt_tcw2[index_old];
- for (i = 0; i < block_size; i++) {
- for (j = 0; j < block_size; j++) {
- for (k = 0; k < block_size; k++) {
+ for (i = 0; i < block_size[0]; i++) {
+ for (j = 0; j < block_size[1]; j++) {
+ for (k = 0; k < block_size[2]; k++) {
int big_index_old = manta_get_index(
xx_o + i, res_noise_old[0], yy_o + j, res_noise_old[1], zz_o + k);
int big_index_new = manta_get_index(
@@ -452,27 +455,32 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *fds,
return;
}
+ const bool is_2D = (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D);
+ const bool is_axis_X = (fds->slice_axis == SLICE_AXIS_X);
+ const bool is_axis_Y = (fds->slice_axis == SLICE_AXIS_Y);
+ const bool is_axis_Z = (fds->slice_axis == SLICE_AXIS_Z);
+
/* Define grid resolutions from longest domain side. */
if (size[0] >= MAX2(size[1], size[2])) {
scale = res / size[0];
fds->scale = size[0] / fabsf(ob->scale[0]);
- fds->base_res[0] = res;
- fds->base_res[1] = max_ii((int)(size[1] * scale + 0.5f), 4);
- fds->base_res[2] = max_ii((int)(size[2] * scale + 0.5f), 4);
+ fds->base_res[0] = (is_2D && is_axis_X) ? 1 : res;
+ fds->base_res[1] = (is_2D && is_axis_Y) ? 1 : max_ii((int)(size[1] * scale + 0.5f), 4);
+ fds->base_res[2] = (is_2D && is_axis_Z) ? 1 : max_ii((int)(size[2] * scale + 0.5f), 4);
}
else if (size[1] >= MAX2(size[0], size[2])) {
scale = res / size[1];
fds->scale = size[1] / fabsf(ob->scale[1]);
- fds->base_res[0] = max_ii((int)(size[0] * scale + 0.5f), 4);
- fds->base_res[1] = res;
- fds->base_res[2] = max_ii((int)(size[2] * scale + 0.5f), 4);
+ fds->base_res[0] = (is_2D && is_axis_X) ? 1 : max_ii((int)(size[0] * scale + 0.5f), 4);
+ fds->base_res[1] = (is_2D && is_axis_Y) ? 1 : res;
+ fds->base_res[2] = (is_2D && is_axis_Z) ? 1 : max_ii((int)(size[2] * scale + 0.5f), 4);
}
else {
scale = res / size[2];
fds->scale = size[2] / fabsf(ob->scale[2]);
- fds->base_res[0] = max_ii((int)(size[0] * scale + 0.5f), 4);
- fds->base_res[1] = max_ii((int)(size[1] * scale + 0.5f), 4);
- fds->base_res[2] = res;
+ fds->base_res[0] = (is_2D && is_axis_X) ? 1 : max_ii((int)(size[0] * scale + 0.5f), 4);
+ fds->base_res[1] = (is_2D && is_axis_Y) ? 1 : max_ii((int)(size[1] * scale + 0.5f), 4);
+ fds->base_res[2] = (is_2D && is_axis_Z) ? 1 : res;
}
/* Set cell size. */
@@ -2267,7 +2275,10 @@ static void adaptive_domain_adjust(
fds->p1[2] = fds->p0[2] + fds->cell_size[2] * fds->base_res[2];
/* adjust domain resolution */
- const int block_size = fds->noise_scale;
+ int block_size[3] = {fds->noise_scale, fds->noise_scale, fds->noise_scale};
+ if (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D) {
+ block_size[fds->slice_axis - 1] = 1;
+ }
int min[3] = {32767, 32767, 32767}, max[3] = {-32767, -32767, -32767}, res[3];
int total_cells = 1, res_changed = 0, shift_changed = 0;
float min_vel[3], max_vel[3];
@@ -2314,13 +2325,13 @@ static void adaptive_domain_adjust(
if (max_den < fds->adapt_threshold && fds->flags & FLUID_DOMAIN_USE_NOISE && fds->fluid) {
int i, j, k;
/* high res grid index */
- int xx = (x - fds->res_min[0]) * block_size;
- int yy = (y - fds->res_min[1]) * block_size;
- int zz = (z - fds->res_min[2]) * block_size;
+ int xx = (x - fds->res_min[0]) * block_size[0];
+ int yy = (y - fds->res_min[1]) * block_size[1];
+ int zz = (z - fds->res_min[2]) * block_size[2];
- for (i = 0; i < block_size; i++) {
- for (j = 0; j < block_size; j++) {
- for (k = 0; k < block_size; k++) {
+ for (i = 0; i < block_size[0]; i++) {
+ for (j = 0; j < block_size[1]; j++) {
+ for (k = 0; k < block_size[2]; k++) {
int big_index = manta_get_index(
xx + i, res_noise[0], yy + j, res_noise[1], zz + k);
float den = (bigfuel) ? MAX2(bigdensity[big_index], bigfuel[big_index]) :
@@ -4706,6 +4717,16 @@ void BKE_fluid_effector_type_set(Object *UNUSED(object), FluidEffectorSettings *
settings->type = type;
}
+void BKE_fluid_domain_solver_res_set(Object *UNUSED(object),
+ FluidDomainSettings *settings,
+ int res)
+{
+ if (res == FLUID_DOMAIN_DIMENSION_2D && settings->slice_axis == SLICE_AXIS_AUTO) {
+ settings->slice_axis = SLICE_AXIS_X;
+ }
+ settings->solver_res = res;
+}
+
void BKE_fluid_fields_sanitize(FluidDomainSettings *settings)
{
/* Based on the domain type, certain fields are defaulted accordingly if the selected field
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index f592b0f97ea..89da2c81f9b 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4379,6 +4379,21 @@ static void particles_fluid_step(ParticleSimulationData *sim,
const float posParticle[3] = {posX, posY, posZ};
copy_v3_v3(pa->state.co, posParticle);
+ /* Adjust particle position for 2d representation. */
+ if (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D) {
+ if (fds->slice_axis == SLICE_AXIS_X) {
+ float tmp = pa->state.co[1];
+ pa->state.co[1] = pa->state.co[0];
+ pa->state.co[0] = pa->state.co[2];
+ pa->state.co[2] = tmp;
+ }
+ if (fds->slice_axis == SLICE_AXIS_Y) {
+ float tmp = pa->state.co[1];
+ pa->state.co[1] = pa->state.co[2];
+ pa->state.co[2] = tmp;
+ }
+ }
+
/* Normalize to unit cube around 0. */
float resDomain[3] = {resX, resY, resZ};
mul_v3_fl(resDomain, 0.5f);
@@ -4412,6 +4427,21 @@ static void particles_fluid_step(ParticleSimulationData *sim,
const float velParticle[3] = {velX, velY, velZ};
copy_v3_v3(pa->state.vel, velParticle);
mul_v3_fl(pa->state.vel, fds->dx);
+
+ /* Adjust particle velocity for 2d representation. */
+ if (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D) {
+ if (fds->slice_axis == SLICE_AXIS_X) {
+ float tmp = pa->state.vel[1];
+ pa->state.vel[0] = pa->state.vel[2];
+ pa->state.vel[1] = pa->state.vel[0];
+ pa->state.vel[2] = tmp;
+ }
+ else if (fds->slice_axis == SLICE_AXIS_Y) {
+ float tmp = pa->state.vel[1];
+ pa->state.vel[1] = pa->state.vel[2];
+ pa->state.vel[2] = tmp;
+ }
+ }
# if 0
/* Debugging: Print particle velocity. */
printf("pa->state.vel[0]: %f, pa->state.vel[1]: %f, pa->state.vel[2]: %f\n",
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index f5be9c846d1..e894c233465 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -1392,15 +1392,20 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
const bool color_range = (fds->gridlines_color_field == FLUID_GRIDLINE_COLOR_TYPE_RANGE &&
fds->use_coba && fds->coba_field != FLUID_DOMAIN_FIELD_FLAGS);
+ const bool is_2D = (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D);
+ const bool is_axis_X = (fds->slice_axis == SLICE_AXIS_X);
+ const bool is_axis_Y = (fds->slice_axis == SLICE_AXIS_Y);
+ const bool is_axis_Z = (fds->slice_axis == SLICE_AXIS_Z);
+
/* Small cube showing voxel size. */
{
float min[3];
madd_v3fl_v3fl_v3fl_v3i(min, fds->p0, fds->cell_size, fds->res_min);
float voxel_cubemat[4][4] = {{0.0f}};
/* scale small cube to voxel size */
- voxel_cubemat[0][0] = fds->cell_size[0] / 2.0f;
- voxel_cubemat[1][1] = fds->cell_size[1] / 2.0f;
- voxel_cubemat[2][2] = fds->cell_size[2] / 2.0f;
+ voxel_cubemat[0][0] = (is_2D && is_axis_X) ? 0.0f : (fds->cell_size[0] / 2.0f);
+ voxel_cubemat[1][1] = (is_2D && is_axis_Y) ? 0.0f : (fds->cell_size[1] / 2.0f);
+ voxel_cubemat[2][2] = (is_2D && is_axis_Z) ? 0.0f : (fds->cell_size[2] / 2.0f);
voxel_cubemat[3][3] = 1.0f;
/* translate small cube to corner */
copy_v3_v3(voxel_cubemat[3], min);
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index daeadce3059..c225e1dc94b 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -92,7 +92,8 @@ static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata,
return;
}
- const bool use_slice = (fds->axis_slice_method == AXIS_SLICE_SINGLE);
+ const bool use_slice = (fds->axis_slice_method == AXIS_SLICE_SINGLE) ||
+ (fds->solver_res == FLUID_DOMAIN_DIMENSION_2D);
const bool show_phi = ELEM(fds->coba_field,
FLUID_DOMAIN_FIELD_PHI,
FLUID_DOMAIN_FIELD_PHI_IN,
diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h
index 5ac5f7ca8a2..fe703182f65 100644
--- a/source/blender/makesdna/DNA_fluid_types.h
+++ b/source/blender/makesdna/DNA_fluid_types.h
@@ -198,6 +198,12 @@ enum {
FLUID_DOMAIN_TYPE_LIQUID = 1,
};
+/* Fluid domain dimension. */
+enum {
+ FLUID_DOMAIN_DIMENSION_2D = 2,
+ FLUID_DOMAIN_DIMENSION_3D = 3,
+};
+
/* Mesh levelset generator types. */
enum {
FLUID_DOMAIN_MESH_IMPROVED = 0,
diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c
index 10e899b7ee3..dedc92caeb5 100644
--- a/source/blender/makesrna/intern/rna_fluid.c
+++ b/source/blender/makesrna/intern/rna_fluid.c
@@ -220,6 +220,16 @@ static void rna_Fluid_reset_dependency(Main *bmain, Scene *scene, PointerRNA *pt
rna_Fluid_dependency_update(bmain, scene, ptr);
}
+static void rna_Fluid_slice_axis_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+# ifdef WITH_FLUID
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ if (settings->solver_res == FLUID_DOMAIN_DIMENSION_2D) {
+ rna_Fluid_domain_data_reset(bmain, scene, ptr);
+ }
+# endif
+}
+
static void rna_Fluid_parts_create(Main *bmain,
PointerRNA *ptr,
const char *pset_name,
@@ -863,6 +873,60 @@ static const EnumPropertyItem *rna_Fluid_data_depth_itemf(bContext *UNUSED(C),
return item;
}
+static const EnumPropertyItem *rna_Fluid_slice_axis_itemf(bContext *UNUSED(C),
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem = 0;
+
+ if (settings->solver_res == FLUID_DOMAIN_DIMENSION_3D) {
+ tmp.value = SLICE_AXIS_AUTO;
+ tmp.identifier = "AUTO";
+ tmp.icon = 0;
+ tmp.name = "Auto";
+ tmp.description = "Adjust slice direction according to the view direction";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+
+ tmp.value = SLICE_AXIS_X;
+ tmp.identifier = "X";
+ tmp.icon = 0;
+ tmp.name = "X";
+ tmp.description = "Slice along the X axis";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ tmp.value = SLICE_AXIS_Y;
+ tmp.identifier = "Y";
+ tmp.icon = 0;
+ tmp.name = "Y";
+ tmp.description = "Slice along the Y axis";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ tmp.value = SLICE_AXIS_Z;
+ tmp.identifier = "Z";
+ tmp.icon = 0;
+ tmp.name = "Z";
+ tmp.description = "Slice along the Z axis";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static void rna_Fluid_solver_res_set(struct PointerRNA *ptr, int value)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ Object *ob = (Object *)ptr->owner_id;
+ BKE_fluid_domain_solver_res_set(ob, settings, value);
+}
+
static void rna_Fluid_domaintype_set(struct PointerRNA *ptr, int value)
{
FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
@@ -1268,6 +1332,12 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
{FLUID_DOMAIN_TYPE_LIQUID, "LIQUID", 0, "Liquid", "Create domain for liquids"},
{0, NULL, 0, NULL, NULL}};
+ static EnumPropertyItem solver_res_items[] = {
+ {FLUID_DOMAIN_DIMENSION_2D, "2D", 0, "2D", "Create 2D domain"},
+ {FLUID_DOMAIN_DIMENSION_3D, "3D", 0, "3D", "Create 3D domain"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem prop_compression_items[] = {
{VDB_COMPRESSION_ZIP, "ZIP", 0, "Zip", "Effective but slow compression"},
# ifdef WITH_OPENVDB_BLOSC
@@ -1351,15 +1421,9 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ /* Axis options are generated dynamically based on domain dimension (2D or 3D). */
static const EnumPropertyItem axis_slice_position_items[] = {
- {SLICE_AXIS_AUTO,
- "AUTO",
- 0,
- "Auto",
- "Adjust slice direction according to the view direction"},
- {SLICE_AXIS_X, "X", 0, "X", "Slice along the X axis"},
- {SLICE_AXIS_Y, "Y", 0, "Y", "Slice along the Y axis"},
- {SLICE_AXIS_Z, "Z", 0, "Z", "Slice along the Z axis"},
+ {0, "NONE", 0, "", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -1670,6 +1734,13 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_flip_parts_update");
+ prop = RNA_def_property(srna, "solver_res", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, solver_res_items);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_solver_res_set", NULL);
+ RNA_def_property_ui_text(prop, "Dimension", "Change the solver resolution");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_datacache_reset");
+
prop = RNA_def_property(srna, "delete_in_obstacle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_DELETE_IN_OBSTACLE);
RNA_def_property_ui_text(prop, "Clear In Obstacle", "Delete fluid inside obstacles");
@@ -2518,8 +2589,9 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "slice_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "slice_axis");
RNA_def_property_enum_items(prop, axis_slice_position_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Fluid_slice_axis_itemf");
RNA_def_property_ui_text(prop, "Axis", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_slice_axis_reset");
prop = RNA_def_property(srna, "slice_per_voxel", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "slice_per_voxel");