diff options
author | Sebastián Barschkis <sebbas@sebbas.org> | 2021-08-09 12:19:42 +0300 |
---|---|---|
committer | Sebastián Barschkis <sebbas@sebbas.org> | 2021-08-09 12:19:42 +0300 |
commit | 4e84e076b2567ee2ec9fc70aced35a3ebd0ad19e (patch) | |
tree | bd81f667cd713eca1c812dd79750820eed943026 | |
parent | 23d5bbd104581550f84c690a42e36ddbea070e21 (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.cpp | 34 | ||||
-rw-r--r-- | intern/mantaflow/intern/strings/fluid_script.h | 31 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_physics_fluid.py | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_fluid.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fluid.c | 73 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 30 | ||||
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_extra.c | 11 | ||||
-rw-r--r-- | source/blender/draw/engines/workbench/workbench_volume.c | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_fluid_types.h | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_fluid.c | 90 |
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"); |