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
path: root/source
diff options
context:
space:
mode:
authorJacques Lucke <mail@jlucke.com>2019-12-17 11:34:13 +0300
committerJacques Lucke <mail@jlucke.com>2019-12-17 11:34:13 +0300
commit9a3b3700615e21fd84ec4204962f010e14b2fc43 (patch)
tree1b073a2a0cd8de2829cf22561b964fd9791acaed /source
parent2b84a7d5b07ff7883997f520b16b467da74515c4 (diff)
parent7d2d2ffa76647871836f779f013c99e474228f3d (diff)
Merge branch 'master' into functions
Diffstat (limited to 'source')
-rw-r--r--source/blender/CMakeLists.txt4
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc13
-rw-r--r--source/blender/blenkernel/BKE_fluid.h69
-rw-r--r--source/blender/blenkernel/BKE_fluidsim.h51
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h3
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h4
-rw-r--r--source/blender/blenkernel/BKE_smoke.h62
-rw-r--r--source/blender/blenkernel/CMakeLists.txt22
-rw-r--r--source/blender/blenkernel/intern/bpath.c10
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c9
-rw-r--r--source/blender/blenkernel/intern/effect.c13
-rw-r--r--source/blender/blenkernel/intern/fluid.c4806
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c90
-rw-r--r--source/blender/blenkernel/intern/image_save.c8
-rw-r--r--source/blender/blenkernel/intern/modifier.c2
-rw-r--r--source/blender/blenkernel/intern/object.c24
-rw-r--r--source/blender/blenkernel/intern/particle.c19
-rw-r--r--source/blender/blenkernel/intern/particle_system.c527
-rw-r--r--source/blender/blenkernel/intern/pointcache.c496
-rw-r--r--source/blender/blenkernel/intern/smoke.c3654
-rw-r--r--source/blender/blenlib/BLI_ghash.h3
-rw-r--r--source/blender/blenlib/BLI_task.h1
-rw-r--r--source/blender/blenlib/intern/BLI_ghash_utils.c9
-rw-r--r--source/blender/blenloader/intern/readfile.c175
-rw-r--r--source/blender/blenloader/intern/versioning_250.c28
-rw-r--r--source/blender/blenloader/intern/versioning_260.c80
-rw-r--r--source/blender/blenloader/intern/versioning_270.c26
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c40
-rw-r--r--source/blender/collada/ExtraTags.h5
-rw-r--r--source/blender/compositor/nodes/COM_DenoiseNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_DenoiseNode.h5
-rw-r--r--source/blender/compositor/operations/COM_DenoiseOperation.cpp5
-rw-r--r--source/blender/compositor/operations/COM_DenoiseOperation.h5
-rw-r--r--source/blender/depsgraph/intern/depsgraph_physics.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h2
-rw-r--r--source/blender/draw/CMakeLists.txt6
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c57
-rw-r--r--source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c7
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_curve.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_text.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c60
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h2
-rw-r--r--source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_frag.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_groundline_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_loose_point_frag.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_loose_point_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_point_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_wire_frag.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl6
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c75
-rw-r--r--source/blender/draw/intern/draw_common.h2
-rw-r--r--source/blender/draw/intern/draw_manager_text.c2
-rw-r--r--source/blender/draw/intern/draw_manager_text.h4
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt3
-rw-r--r--source/blender/editors/include/ED_mball.h1
-rw-r--r--source/blender/editors/include/ED_transform.h3
-rw-r--r--source/blender/editors/include/UI_icons.h2
-rw-r--r--source/blender/editors/interface/interface_templates.c10
-rw-r--r--source/blender/editors/physics/CMakeLists.txt14
-rw-r--r--source/blender/editors/physics/particle_object.c2
-rw-r--r--source/blender/editors/physics/physics_fluid.c1647
-rw-r--r--source/blender/editors/physics/physics_intern.h14
-rw-r--r--source/blender/editors/physics/physics_ops.c14
-rw-r--r--source/blender/editors/screen/screen_ops.c17
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c29
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c17
-rw-r--r--source/blender/editors/space_image/image_draw.c9
-rw-r--r--source/blender/editors/space_image/image_ops.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c6
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt6
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c25
-rw-r--r--source/blender/editors/transform/transform_snap.h2
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c7
-rw-r--r--source/blender/gpu/CMakeLists.txt7
-rw-r--r--source/blender/gpu/GPU_buffers.h2
-rw-r--r--source/blender/gpu/GPU_draw.h14
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c22
-rw-r--r--source/blender/gpu/intern/gpu_draw.c388
-rw-r--r--source/blender/gpu/intern/gpu_draw_smoke.c416
-rw-r--r--source/blender/makesdna/DNA_armature_types.h6
-rw-r--r--source/blender/makesdna/DNA_camera_types.h2
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h4
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_fluid_types.h590
-rw-r--r--source/blender/makesdna/DNA_image_types.h2
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h35
-rw-r--r--source/blender/makesdna/DNA_node_types.h2
-rw-r--r--source/blender/makesdna/DNA_object_types.h3
-rw-r--r--source/blender/makesdna/DNA_particle_types.h38
-rw-r--r--source/blender/makesdna/DNA_scene_types.h6
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h346
-rw-r--r--source/blender/makesdna/DNA_sound_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h6
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h8
-rw-r--r--source/blender/makesdna/intern/dna_rename_defs.h7
-rw-r--r--source/blender/makesdna/intern/makesdna.c7
-rw-r--r--source/blender/makesrna/RNA_access.h11
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt13
-rw-r--r--source/blender/makesrna/intern/makesrna.c3
-rw-r--r--source/blender/makesrna/intern/rna_brush.c45
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c2590
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c792
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c4
-rw-r--r--source/blender/makesrna/intern/rna_image.c3
-rw-r--r--source/blender/makesrna/intern/rna_internal.h3
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c84
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c2
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c8
-rw-r--r--source/blender/makesrna/intern/rna_particle.c5
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c1218
-rw-r--r--source/blender/modifiers/CMakeLists.txt8
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h2
-rw-r--r--source/blender/modifiers/intern/MOD_fluid.c (renamed from source/blender/modifiers/intern/MOD_smoke.c)128
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c150
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.c588
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.h39
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_util.h6
-rw-r--r--source/blender/modifiers/intern/MOD_util.c3
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_denoise.c8
-rw-r--r--source/blender/python/intern/CMakeLists.txt9
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c21
-rw-r--r--source/blender/python/intern/bpy_interface.c17
-rw-r--r--source/blender/render/CMakeLists.txt6
-rw-r--r--source/blender/shader_fx/CMakeLists.txt1
-rw-r--r--source/blender/usd/intern/abstract_hierarchy_iterator.h6
-rw-r--r--source/blender/usd/intern/usd_exporter_context.h6
-rw-r--r--source/blender/usd/intern/usd_hierarchy_iterator.h6
-rw-r--r--source/blender/usd/intern/usd_writer_abstract.h6
-rw-r--r--source/blender/usd/intern/usd_writer_camera.h6
-rw-r--r--source/blender/usd/intern/usd_writer_hair.h6
-rw-r--r--source/blender/usd/intern/usd_writer_light.h6
-rw-r--r--source/blender/usd/intern/usd_writer_mesh.h6
-rw-r--r--source/blender/usd/intern/usd_writer_transform.h6
-rw-r--r--source/blender/usd/usd.h6
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c15
-rw-r--r--source/creator/CMakeLists.txt2
-rw-r--r--source/creator/creator.c7
149 files changed, 10506 insertions, 9638 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 9de4c901a3e..22ed2eff2a9 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -32,12 +32,14 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_color_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_constraint_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_curve_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_curveprofile_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_customdata_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_defs.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_documentation.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_dynamicpaint_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_effect_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_fileglobal_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_fluid_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_freestyle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_genfile.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_modifier_types.h
@@ -68,14 +70,12 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_outliner_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_types.h
- ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_curveprofile_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_rigidbody_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_screen_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sdna_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sequence_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_shader_fx_types.h
- ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_smoke_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sound_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_space_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_speaker_types.h
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index d422a3c023e..5d9f92432d1 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -42,6 +42,7 @@ extern "C" {
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h" /* for FILE_MAX */
+#include "DNA_fluid_types.h"
#include "BLI_string.h"
@@ -105,11 +106,12 @@ ExportSettings::ExportSettings()
static bool object_is_smoke_sim(Object *ob)
{
- ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid);
if (md) {
- SmokeModifierData *smd = reinterpret_cast<SmokeModifierData *>(md);
- return (smd->type == MOD_SMOKE_TYPE_DOMAIN);
+ FluidModifierData *smd = reinterpret_cast<FluidModifierData *>(md);
+ return (smd->type == MOD_FLUID_TYPE_DOMAIN && smd->domain &&
+ smd->domain->type == FLUID_DOMAIN_TYPE_GAS);
}
return false;
@@ -553,7 +555,10 @@ void AbcExporter::createParticleSystemsWriters(Object *ob, AbcTransformWriter *x
m_settings.export_child_hairs = true;
m_shapes.push_back(new AbcHairWriter(ob, xform, m_shape_sampling_index, m_settings, psys));
}
- else if (m_settings.export_particles && psys->part->type == PART_EMITTER) {
+ else if (m_settings.export_particles &&
+ (psys->part->type & PART_EMITTER || psys->part->type & PART_FLUID_FLIP ||
+ psys->part->type & PART_FLUID_SPRAY || psys->part->type & PART_FLUID_BUBBLE ||
+ psys->part->type & PART_FLUID_FOAM || psys->part->type & PART_FLUID_TRACER)) {
m_shapes.push_back(new AbcPointsWriter(ob, xform, m_shape_sampling_index, m_settings, psys));
}
}
diff --git a/source/blender/blenkernel/BKE_fluid.h b/source/blender/blenkernel/BKE_fluid.h
new file mode 100644
index 00000000000..3e389cfec58
--- /dev/null
+++ b/source/blender/blenkernel/BKE_fluid.h
@@ -0,0 +1,69 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ */
+
+#ifndef __BKE_FLUID_H__
+#define __BKE_FLUID_H__
+
+/** \file
+ * \ingroup bke
+ */
+
+struct FluidDomainSettings;
+struct FluidModifierData;
+struct Scene;
+
+typedef float (*BKE_Fluid_BresenhamFn)(
+ float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
+
+struct Mesh *BKE_fluid_modifier_do(struct FluidModifierData *mmd,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct Mesh *me);
+
+void BKE_fluid_modifier_free(struct FluidModifierData *mmd);
+void BKE_fluid_modifier_reset(struct FluidModifierData *mmd);
+void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd);
+void BKE_fluid_modifier_copy(const struct FluidModifierData *mmd,
+ struct FluidModifierData *tmmd,
+ const int flag);
+
+void BKE_fluid_reallocate_fluid(struct FluidDomainSettings *mds, int res[3], int free_old);
+void BKE_fluid_reallocate_copy_fluid(struct FluidDomainSettings *mds,
+ int o_res[3],
+ int n_res[3],
+ int o_min[3],
+ int n_min[3],
+ int o_max[3],
+ int o_shift[3],
+ int n_shift[3]);
+void BKE_fluid_cache_free(struct FluidDomainSettings *mds, struct Object *ob, int cache_map);
+
+float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3]);
+int BKE_fluid_get_data_flags(struct FluidDomainSettings *mds);
+
+void BKE_fluid_particle_system_create(struct Main *bmain,
+ struct Object *ob,
+ const char *pset_name,
+ const char *parts_name,
+ const char *psys_name,
+ const int psys_type);
+void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_type);
+
+#endif /* __BKE_FLUID_H__ */
diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h
deleted file mode 100644
index d44c88c30a9..00000000000
--- a/source/blender/blenkernel/BKE_fluidsim.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- */
-
-#ifndef __BKE_FLUIDSIM_H__
-#define __BKE_FLUIDSIM_H__
-
-/** \file
- * \ingroup bke
- */
-
-struct Depsgraph;
-struct FluidsimSettings;
-struct MVert;
-struct Object;
-struct Scene;
-
-/* old interface */
-
-void initElbeemMesh(struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- int *numVertices,
- float **vertices,
- int *numTriangles,
- int **triangles,
- int useGlobalCoords,
- int modifierIndex);
-
-/* bounding box & memory estimate */
-void fluid_get_bb(
- struct MVert *mvert, int totvert, float obmat[4][4], float start[3], float size[3]);
-
-void fluid_estimate_memory(struct Object *ob, struct FluidsimSettings *fss, char *value);
-
-#endif
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 570203081fe..9eb10d296de 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -40,15 +40,14 @@ struct CustomData;
struct DMFlagMat;
struct GPU_PBVH_Buffers;
struct IsectRayPrecalc;
-struct Mesh;
struct MLoop;
struct MLoopTri;
struct MPoly;
struct MVert;
+struct Mesh;
struct PBVH;
struct PBVHNode;
struct SubdivCCG;
-struct TaskParallelSettings;
struct TaskParallelTLS;
typedef struct PBVH PBVH;
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 6ce60081f5b..fd29480cac7 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -75,6 +75,7 @@
/* Structs */
struct ClothModifierData;
+struct FluidModifierData;
struct ListBase;
struct Main;
struct Object;
@@ -83,7 +84,6 @@ struct ParticleSystem;
struct PointCache;
struct RigidBodyWorld;
struct Scene;
-struct SmokeModifierData;
struct SoftBody;
struct ViewLayer;
@@ -286,7 +286,7 @@ void BKE_ptcache_make_particle_key(struct ParticleKey *key, int index, void **da
void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb);
void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys);
void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd);
-void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd);
+void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct FluidModifierData *mmd);
void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid,
struct Object *ob,
struct DynamicPaintSurface *surface);
diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h
deleted file mode 100644
index 10632d47203..00000000000
--- a/source/blender/blenkernel/BKE_smoke.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation.
- * All rights reserved.
- */
-
-#ifndef __BKE_SMOKE_H__
-#define __BKE_SMOKE_H__
-
-/** \file
- * \ingroup bke
- */
-
-struct Scene;
-struct SmokeDomainSettings;
-struct SmokeModifierData;
-
-typedef float (*bresenham_callback)(
- float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
-
-struct Mesh *smokeModifier_do(struct SmokeModifierData *smd,
- struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- struct Mesh *me);
-
-void smokeModifier_free(struct SmokeModifierData *smd);
-void smokeModifier_reset(struct SmokeModifierData *smd);
-void smokeModifier_reset_turbulence(struct SmokeModifierData *smd);
-void smokeModifier_createType(struct SmokeModifierData *smd);
-void smokeModifier_copy(const struct SmokeModifierData *smd,
- struct SmokeModifierData *tsmd,
- const int flag);
-
-void BKE_smoke_reallocate_fluid(struct SmokeDomainSettings *sds,
- float dx,
- int res[3],
- int free_old);
-void BKE_smoke_reallocate_highres_fluid(struct SmokeDomainSettings *sds,
- float dx,
- int res[3],
- int free_old);
-
-float BKE_smoke_get_velocity_at(struct Object *ob, float position[3], float velocity[3]);
-int BKE_smoke_get_data_flags(struct SmokeDomainSettings *sds);
-
-bool BKE_smoke_show_highres(struct Scene *scene, struct SmokeDomainSettings *sds);
-
-#endif /* __BKE_SMOKE_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 3c912a4da70..053d9c17e1a 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -45,11 +45,11 @@ set(INC
../../../intern/atomic
../../../intern/clog
../../../intern/libmv
+ ../../../intern/mantaflow/extern
../../../intern/memutil
../../../intern/mikktspace
../../../intern/opensubdiv
../../../extern/curve_fit_nd
- ../../../intern/smoke/extern
# dna_type_offsets.h
${CMAKE_CURRENT_BINARY_DIR}/../makesdna/intern
@@ -114,7 +114,7 @@ set(SRC
intern/editmesh_tangent.c
intern/effect.c
intern/fcurve.c
- intern/fluidsim.c
+ intern/fluid.c
intern/fmodifier.c
intern/font.c
intern/freestyle.c
@@ -201,7 +201,6 @@ set(SRC
intern/sequencer.c
intern/shader_fx.c
intern/shrinkwrap.c
- intern/smoke.c
intern/softbody.c
intern/sound.c
intern/speaker.c
@@ -286,7 +285,7 @@ set(SRC
BKE_editmesh_tangent.h
BKE_effect.h
BKE_fcurve.h
- BKE_fluidsim.h
+ BKE_fluid.h
BKE_font.h
BKE_freestyle.h
BKE_global.h
@@ -349,7 +348,6 @@ set(SRC
BKE_sequencer.h
BKE_shader_fx.h
BKE_shrinkwrap.h
- BKE_smoke.h
BKE_softbody.h
BKE_sound.h
BKE_speaker.h
@@ -536,20 +534,10 @@ if(WITH_PYTHON)
endif()
if(WITH_MOD_FLUID)
- list(APPEND INC
- ../../../intern/elbeem/extern
- )
- list(APPEND LIB
- bf_intern_elbeem
- )
- add_definitions(-DWITH_MOD_FLUID)
-endif()
-
-if(WITH_MOD_SMOKE)
list(APPEND LIB
- bf_intern_smoke
+ bf_intern_mantaflow
)
- add_definitions(-DWITH_SMOKE)
+ add_definitions(-DWITH_FLUID)
endif()
if(WITH_MOD_OCEANSIM)
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index de7837cdd90..90b26f8c288 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -59,7 +59,7 @@
#include "DNA_texture_types.h"
#include "DNA_vfont_types.h"
#include "DNA_scene_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_freestyle_types.h"
#include "BLI_blenlib.h"
@@ -498,10 +498,10 @@ void BKE_bpath_traverse_id(
rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data);
}
}
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]);
+ else if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN && mmd->domain) {
+ rewrite_path_fixed(mmd->domain->cache_directory, visit_cb, absbase, bpath_user_data);
}
}
else if (md->type == eModifierType_Cloth) {
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 91b169590ac..74a523bfbdc 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -6278,7 +6278,14 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph,
/* Apply brush on the surface depending on it's collision type */
if (brush->psys && brush->psys->part &&
- ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) &&
+ ELEM(brush->psys->part->type,
+ PART_EMITTER,
+ PART_FLUID,
+ PART_FLUID_FLIP,
+ PART_FLUID_SPRAY,
+ PART_FLUID_BUBBLE,
+ PART_FLUID_FOAM,
+ PART_FLUID_TRACER) &&
psys_check_enabled(brushObj, brush->psys, for_render)) {
/* Paint a particle system */
dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index ffab82b75af..8971021329a 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -62,7 +62,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
-#include "BKE_smoke.h"
+#include "BKE_fluid.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_physics.h"
@@ -71,13 +71,6 @@
#include "RE_render_ext.h"
#include "RE_shader_ext.h"
-/* fluid sim particle import */
-#ifdef WITH_MOD_FLUID
-# include "LBM_fluidsim.h"
-# include <zlib.h>
-# include <string.h>
-#endif // WITH_MOD_FLUID
-
EffectorWeights *BKE_effector_add_weights(Collection *collection)
{
EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights");
@@ -1031,9 +1024,10 @@ static void do_physical_effector(EffectorCache *eff,
break;
case PFIELD_SMOKEFLOW:
zero_v3(force);
+#ifdef WITH_FLUID
if (pd->f_source) {
float density;
- if ((density = BKE_smoke_get_velocity_at(pd->f_source, point->loc, force)) >= 0.0f) {
+ if ((density = BKE_fluid_get_velocity_at(pd->f_source, point->loc, force)) >= 0.0f) {
float influence = strength * efd->falloff;
if (pd->flag & PFIELD_SMOKE_DENSITY) {
influence *= density;
@@ -1043,6 +1037,7 @@ static void do_physical_effector(EffectorCache *eff,
madd_v3_v3fl(total_force, point->vel, -pd->f_flow * influence);
}
}
+#endif
break;
}
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
new file mode 100644
index 00000000000..81c7c700cc2
--- /dev/null
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -0,0 +1,4806 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#ifdef WITH_FLUID
+
+# include "MEM_guardedalloc.h"
+
+# include <float.h>
+# include <math.h>
+# include <stdio.h>
+# include <string.h> /* memset */
+
+# include "BLI_blenlib.h"
+# include "BLI_math.h"
+# include "BLI_kdopbvh.h"
+# include "BLI_threads.h"
+# include "BLI_utildefines.h"
+
+# include "DNA_customdata_types.h"
+# include "DNA_light_types.h"
+# include "DNA_mesh_types.h"
+# include "DNA_meshdata_types.h"
+# include "DNA_modifier_types.h"
+# include "DNA_object_types.h"
+# include "DNA_particle_types.h"
+# include "DNA_scene_types.h"
+# include "DNA_fluid_types.h"
+
+# include "BKE_bvhutils.h"
+# include "BKE_collision.h"
+# include "BKE_colortools.h"
+# include "BKE_customdata.h"
+# include "BKE_deform.h"
+# include "BKE_effect.h"
+# include "BKE_library.h"
+# include "BKE_mesh.h"
+# include "BKE_mesh_runtime.h"
+# include "BKE_modifier.h"
+# include "BKE_object.h"
+# include "BKE_particle.h"
+# include "BKE_pointcache.h"
+# include "BKE_scene.h"
+# include "BKE_fluid.h"
+# include "BKE_texture.h"
+
+# include "DEG_depsgraph.h"
+# include "DEG_depsgraph_query.h"
+
+# include "RE_shader_ext.h"
+
+# include "manta_fluid_API.h"
+
+# include "BLI_task.h"
+# include "BLI_kdtree.h"
+# include "BLI_voxel.h"
+
+// #define DEBUG_PRINT
+
+static ThreadMutex object_update_lock = BLI_MUTEX_INITIALIZER;
+
+struct FluidModifierData;
+struct Mesh;
+struct Object;
+struct Scene;
+
+// timestep default value for nice appearance 0.1f
+# define DT_DEFAULT 0.1f
+
+# define ADD_IF_LOWER_POS(a, b) (min_ff((a) + (b), max_ff((a), (b))))
+# define ADD_IF_LOWER_NEG(a, b) (max_ff((a) + (b), min_ff((a), (b))))
+# define ADD_IF_LOWER(a, b) (((b) > 0) ? ADD_IF_LOWER_POS((a), (b)) : ADD_IF_LOWER_NEG((a), (b)))
+
+void BKE_fluid_reallocate_fluid(FluidDomainSettings *mds, int res[3], int free_old)
+{
+ if (free_old && mds->fluid) {
+ manta_free(mds->fluid);
+ }
+ if (!min_iii(res[0], res[1], res[2])) {
+ mds->fluid = NULL;
+ return;
+ }
+
+ mds->fluid = manta_init(res, mds->mmd);
+
+ mds->res_noise[0] = res[0] * mds->noise_scale;
+ mds->res_noise[1] = res[1] * mds->noise_scale;
+ mds->res_noise[2] = res[2] * mds->noise_scale;
+}
+
+void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *mds,
+ int o_res[3],
+ int n_res[3],
+ int o_min[3],
+ int n_min[3],
+ int o_max[3],
+ int o_shift[3],
+ int n_shift[3])
+{
+ int x, y, z;
+ struct MANTA *fluid_old = mds->fluid;
+ const int block_size = mds->noise_scale;
+ int new_shift[3] = {0};
+ sub_v3_v3v3_int(new_shift, n_shift, o_shift);
+
+ /* allocate new fluid data */
+ BKE_fluid_reallocate_fluid(mds, n_res, 0);
+
+ int o_total_cells = o_res[0] * o_res[1] * o_res[2];
+ int n_total_cells = n_res[0] * n_res[1] * n_res[2];
+
+ /* boundary cells will be skipped when copying data */
+ int bwidth = mds->boundary_width;
+
+ /* copy values from old fluid to new */
+ if (o_total_cells > 1 && n_total_cells > 1) {
+ /* base smoke */
+ float *o_dens, *o_react, *o_flame, *o_fuel, *o_heat, *o_vx, *o_vy, *o_vz, *o_r, *o_g, *o_b;
+ float *n_dens, *n_react, *n_flame, *n_fuel, *n_heat, *n_vx, *n_vy, *n_vz, *n_r, *n_g, *n_b;
+ float dummy, *dummy_s;
+ int *dummy_p;
+ /* noise smoke */
+ int wt_res_old[3];
+ float *o_wt_dens, *o_wt_react, *o_wt_flame, *o_wt_fuel, *o_wt_tcu, *o_wt_tcv, *o_wt_tcw,
+ *o_wt_tcu2, *o_wt_tcv2, *o_wt_tcw2, *o_wt_r, *o_wt_g, *o_wt_b;
+ float *n_wt_dens, *n_wt_react, *n_wt_flame, *n_wt_fuel, *n_wt_tcu, *n_wt_tcv, *n_wt_tcw,
+ *n_wt_tcu2, *n_wt_tcv2, *n_wt_tcw2, *n_wt_r, *n_wt_g, *n_wt_b;
+
+ if (mds->flags & FLUID_DOMAIN_USE_NOISE) {
+ manta_smoke_turbulence_export(fluid_old,
+ &o_wt_dens,
+ &o_wt_react,
+ &o_wt_flame,
+ &o_wt_fuel,
+ &o_wt_r,
+ &o_wt_g,
+ &o_wt_b,
+ &o_wt_tcu,
+ &o_wt_tcv,
+ &o_wt_tcw,
+ &o_wt_tcu2,
+ &o_wt_tcv2,
+ &o_wt_tcw2);
+ manta_smoke_turbulence_get_res(fluid_old, wt_res_old);
+ manta_smoke_turbulence_export(mds->fluid,
+ &n_wt_dens,
+ &n_wt_react,
+ &n_wt_flame,
+ &n_wt_fuel,
+ &n_wt_r,
+ &n_wt_g,
+ &n_wt_b,
+ &n_wt_tcu,
+ &n_wt_tcv,
+ &n_wt_tcw,
+ &n_wt_tcu2,
+ &n_wt_tcv2,
+ &n_wt_tcw2);
+ }
+
+ manta_smoke_export(fluid_old,
+ &dummy,
+ &dummy,
+ &o_dens,
+ &o_react,
+ &o_flame,
+ &o_fuel,
+ &o_heat,
+ &o_vx,
+ &o_vy,
+ &o_vz,
+ &o_r,
+ &o_g,
+ &o_b,
+ &dummy_p,
+ &dummy_s);
+ manta_smoke_export(mds->fluid,
+ &dummy,
+ &dummy,
+ &n_dens,
+ &n_react,
+ &n_flame,
+ &n_fuel,
+ &n_heat,
+ &n_vx,
+ &n_vy,
+ &n_vz,
+ &n_r,
+ &n_g,
+ &n_b,
+ &dummy_p,
+ &dummy_s);
+
+ for (x = o_min[0]; x < o_max[0]; x++) {
+ for (y = o_min[1]; y < o_max[1]; y++) {
+ for (z = o_min[2]; z < o_max[2]; z++) {
+ /* old grid index */
+ int xo = x - o_min[0];
+ int yo = y - o_min[1];
+ int zo = z - o_min[2];
+ int index_old = manta_get_index(xo, o_res[0], yo, o_res[1], zo);
+ /* new grid index */
+ int xn = x - n_min[0] - new_shift[0];
+ int yn = y - n_min[1] - new_shift[1];
+ int zn = z - n_min[2] - new_shift[2];
+ int index_new = manta_get_index(xn, n_res[0], yn, n_res[1], zn);
+
+ /* skip if outside new domain */
+ if (xn < 0 || xn >= n_res[0] || yn < 0 || yn >= n_res[1] || zn < 0 || zn >= n_res[2]) {
+ continue;
+ }
+ /* skip if trying to copy from old boundary cell */
+ if (xo < bwidth || yo < bwidth || zo < bwidth || xo >= o_res[0] - bwidth ||
+ yo >= o_res[1] - bwidth || zo >= o_res[2] - bwidth) {
+ continue;
+ }
+ /* skip if trying to copy into new boundary cell */
+ if (xn < bwidth || yn < bwidth || zn < bwidth || xn >= n_res[0] - bwidth ||
+ yn >= n_res[1] - bwidth || zn >= n_res[2] - bwidth) {
+ continue;
+ }
+
+ /* copy data */
+ if (mds->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;
+ /* new grid index */
+ int xx_n = xn * block_size;
+ int yy_n = yn * block_size;
+ int zz_n = zn * block_size;
+
+ /* insert old texture values into new texture grids */
+ n_wt_tcu[index_new] = o_wt_tcu[index_old];
+ n_wt_tcv[index_new] = o_wt_tcv[index_old];
+ n_wt_tcw[index_new] = o_wt_tcw[index_old];
+
+ n_wt_tcu2[index_new] = o_wt_tcu2[index_old];
+ 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++) {
+ int big_index_old = manta_get_index(
+ xx_o + i, wt_res_old[0], yy_o + j, wt_res_old[1], zz_o + k);
+ int big_index_new = manta_get_index(
+ xx_n + i, mds->res_noise[0], yy_n + j, mds->res_noise[1], zz_n + k);
+ /* copy data */
+ n_wt_dens[big_index_new] = o_wt_dens[big_index_old];
+ if (n_wt_flame && o_wt_flame) {
+ n_wt_flame[big_index_new] = o_wt_flame[big_index_old];
+ n_wt_fuel[big_index_new] = o_wt_fuel[big_index_old];
+ n_wt_react[big_index_new] = o_wt_react[big_index_old];
+ }
+ if (n_wt_r && o_wt_r) {
+ n_wt_r[big_index_new] = o_wt_r[big_index_old];
+ n_wt_g[big_index_new] = o_wt_g[big_index_old];
+ n_wt_b[big_index_new] = o_wt_b[big_index_old];
+ }
+ }
+ }
+ }
+ }
+
+ n_dens[index_new] = o_dens[index_old];
+ /* heat */
+ if (n_heat && o_heat) {
+ n_heat[index_new] = o_heat[index_old];
+ }
+ /* fuel */
+ if (n_fuel && o_fuel) {
+ n_flame[index_new] = o_flame[index_old];
+ n_fuel[index_new] = o_fuel[index_old];
+ n_react[index_new] = o_react[index_old];
+ }
+ /* color */
+ if (o_r && n_r) {
+ n_r[index_new] = o_r[index_old];
+ n_g[index_new] = o_g[index_old];
+ n_b[index_new] = o_b[index_old];
+ }
+ n_vx[index_new] = o_vx[index_old];
+ n_vy[index_new] = o_vy[index_old];
+ n_vz[index_new] = o_vz[index_old];
+ }
+ }
+ }
+ }
+ manta_free(fluid_old);
+}
+
+void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map)
+{
+ char temp_dir[FILE_MAX];
+ int flags = mds->cache_flag;
+
+ /* Ensure cache directory is not relative */
+ const char *relbase = modifier_path_relbase_from_global(ob);
+ BLI_path_abs(mds->cache_directory, relbase);
+
+ if (cache_map & FLUID_DOMAIN_OUTDATED_DATA) {
+ flags &= ~(FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA);
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL);
+ if (BLI_exists(temp_dir)) {
+ BLI_delete(temp_dir, true, true);
+ }
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL);
+ if (BLI_exists(temp_dir)) {
+ BLI_delete(temp_dir, true, true);
+ }
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL);
+ if (BLI_exists(temp_dir)) {
+ BLI_delete(temp_dir, true, true);
+ }
+ mds->cache_frame_pause_data = 0;
+ }
+ if (cache_map & FLUID_DOMAIN_OUTDATED_NOISE) {
+ flags &= ~(FLUID_DOMAIN_BAKING_NOISE | FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_OUTDATED_NOISE);
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL);
+ if (BLI_exists(temp_dir)) {
+ BLI_delete(temp_dir, true, true);
+ }
+ mds->cache_frame_pause_noise = 0;
+ }
+ if (cache_map & FLUID_DOMAIN_OUTDATED_MESH) {
+ flags &= ~(FLUID_DOMAIN_BAKING_MESH | FLUID_DOMAIN_BAKED_MESH | FLUID_DOMAIN_OUTDATED_MESH);
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL);
+ if (BLI_exists(temp_dir)) {
+ BLI_delete(temp_dir, true, true);
+ }
+ mds->cache_frame_pause_mesh = 0;
+ }
+ if (cache_map & FLUID_DOMAIN_OUTDATED_PARTICLES) {
+ flags &= ~(FLUID_DOMAIN_BAKING_PARTICLES | FLUID_DOMAIN_BAKED_PARTICLES |
+ FLUID_DOMAIN_OUTDATED_PARTICLES);
+ BLI_path_join(
+ temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL);
+ if (BLI_exists(temp_dir)) {
+ BLI_delete(temp_dir, true, true);
+ }
+ mds->cache_frame_pause_particles = 0;
+ }
+
+ if (cache_map & FLUID_DOMAIN_OUTDATED_GUIDE) {
+ flags &= ~(FLUID_DOMAIN_BAKING_GUIDE | FLUID_DOMAIN_BAKED_GUIDE | FLUID_DOMAIN_OUTDATED_GUIDE);
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL);
+ if (BLI_exists(temp_dir)) {
+ BLI_delete(temp_dir, true, true);
+ }
+ mds->cache_frame_pause_guide = 0;
+ }
+ mds->cache_flag = flags;
+}
+
+/* convert global position to domain cell space */
+static void manta_pos_to_cell(FluidDomainSettings *mds, float pos[3])
+{
+ mul_m4_v3(mds->imat, pos);
+ sub_v3_v3(pos, mds->p0);
+ pos[0] *= 1.0f / mds->cell_size[0];
+ pos[1] *= 1.0f / mds->cell_size[1];
+ pos[2] *= 1.0f / mds->cell_size[2];
+}
+
+/* Set domain transformations and base resolution from object mesh. */
+static void manta_set_domain_from_mesh(FluidDomainSettings *mds,
+ Object *ob,
+ Mesh *me,
+ bool init_resolution)
+{
+ size_t i;
+ float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+ float size[3];
+ MVert *verts = me->mvert;
+ float scale = 0.0;
+ int res;
+
+ res = mds->maxres;
+
+ /* Set minimum and maximum coordinates of BB. */
+ for (i = 0; i < me->totvert; i++) {
+ minmax_v3v3_v3(min, max, verts[i].co);
+ }
+
+ /* Set domain bounds. */
+ copy_v3_v3(mds->p0, min);
+ copy_v3_v3(mds->p1, max);
+ mds->dx = 1.0f / res;
+
+ /* Calculate domain dimensions. */
+ sub_v3_v3v3(size, max, min);
+ if (init_resolution) {
+ zero_v3_int(mds->base_res);
+ copy_v3_v3(mds->cell_size, size);
+ }
+ /* Apply object scale. */
+ for (i = 0; i < 3; i++) {
+ size[i] = fabsf(size[i] * ob->scale[i]);
+ }
+ copy_v3_v3(mds->global_size, size);
+ copy_v3_v3(mds->dp0, min);
+
+ invert_m4_m4(mds->imat, ob->obmat);
+
+ /* Prevent crash when initializing a plane as domain. */
+ if (!init_resolution || (size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) ||
+ (size[2] < FLT_EPSILON)) {
+ return;
+ }
+
+ /* Define grid resolutions from longest domain side. */
+ if (size[0] >= MAX2(size[1], size[2])) {
+ scale = res / size[0];
+ mds->scale = size[0] / fabsf(ob->scale[0]);
+ mds->base_res[0] = res;
+ mds->base_res[1] = max_ii((int)(size[1] * scale + 0.5f), 4);
+ mds->base_res[2] = max_ii((int)(size[2] * scale + 0.5f), 4);
+ }
+ else if (size[1] >= MAX2(size[0], size[2])) {
+ scale = res / size[1];
+ mds->scale = size[1] / fabsf(ob->scale[1]);
+ mds->base_res[0] = max_ii((int)(size[0] * scale + 0.5f), 4);
+ mds->base_res[1] = res;
+ mds->base_res[2] = max_ii((int)(size[2] * scale + 0.5f), 4);
+ }
+ else {
+ scale = res / size[2];
+ mds->scale = size[2] / fabsf(ob->scale[2]);
+ mds->base_res[0] = max_ii((int)(size[0] * scale + 0.5f), 4);
+ mds->base_res[1] = max_ii((int)(size[1] * scale + 0.5f), 4);
+ mds->base_res[2] = res;
+ }
+
+ /* Set cell size. */
+ mds->cell_size[0] /= (float)mds->base_res[0];
+ mds->cell_size[1] /= (float)mds->base_res[1];
+ mds->cell_size[2] /= (float)mds->base_res[2];
+}
+
+static void manta_set_domain_gravity(Scene *scene, FluidDomainSettings *mds)
+{
+ float gravity[3] = {0.0f, 0.0f, -1.0f};
+ float gravity_mag;
+
+ /* Use global gravity if enabled. */
+ if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
+ copy_v3_v3(gravity, scene->physics_settings.gravity);
+ /* Map default value to 1.0. */
+ mul_v3_fl(gravity, 1.0f / 9.810f);
+
+ /* Convert gravity to domain space. */
+ gravity_mag = len_v3(gravity);
+ mul_mat3_m4_v3(mds->imat, gravity);
+ normalize_v3(gravity);
+ mul_v3_fl(gravity, gravity_mag);
+
+ copy_v3_v3(mds->gravity, gravity);
+ }
+}
+
+static bool BKE_fluid_modifier_init(
+ FluidModifierData *mmd, Depsgraph *depsgraph, Object *ob, Scene *scene, Mesh *me)
+{
+ int scene_framenr = (int)DEG_get_ctime(depsgraph);
+
+ if ((mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain && !mmd->domain->fluid) {
+ FluidDomainSettings *mds = mmd->domain;
+ int res[3];
+ /* Set domain dimensions from mesh. */
+ manta_set_domain_from_mesh(mds, ob, me, true);
+ /* Set domain gravity. */
+ manta_set_domain_gravity(scene, mds);
+ /* Reset domain values. */
+ zero_v3_int(mds->shift);
+ zero_v3(mds->shift_f);
+ add_v3_fl(mds->shift_f, 0.5f);
+ zero_v3(mds->prev_loc);
+ mul_m4_v3(ob->obmat, mds->prev_loc);
+ copy_m4_m4(mds->obmat, ob->obmat);
+
+ /* Set resolutions. */
+ if (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS &&
+ mmd->domain->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
+ res[0] = res[1] = res[2] = 1; /* Use minimum res for adaptive init. */
+ }
+ else {
+ copy_v3_v3_int(res, mds->base_res);
+ }
+ copy_v3_v3_int(mds->res, res);
+ mds->total_cells = mds->res[0] * mds->res[1] * mds->res[2];
+ mds->res_min[0] = mds->res_min[1] = mds->res_min[2] = 0;
+ copy_v3_v3_int(mds->res_max, res);
+
+ /* Set time, frame length = 0.1 is at 25fps. */
+ float fps = scene->r.frs_sec / scene->r.frs_sec_base;
+ mds->frame_length = DT_DEFAULT * (25.0f / fps) * mds->time_scale;
+ /* Initially dt is equal to frame length (dt can change with adaptive-time stepping though). */
+ mds->dt = mds->frame_length;
+ mds->time_per_frame = 0;
+ mds->time_total = (scene_framenr - 1) * mds->frame_length;
+
+ /* Allocate fluid. */
+ BKE_fluid_reallocate_fluid(mds, mds->res, 0);
+
+ mmd->time = scene_framenr;
+
+ return true;
+ }
+ else if (mmd->type & MOD_FLUID_TYPE_FLOW) {
+ if (!mmd->flow) {
+ BKE_fluid_modifier_create_type_data(mmd);
+ }
+ mmd->time = scene_framenr;
+ return true;
+ }
+ else if (mmd->type & MOD_FLUID_TYPE_EFFEC) {
+ if (!mmd->effector) {
+ BKE_fluid_modifier_create_type_data(mmd);
+ }
+ mmd->time = scene_framenr;
+ return true;
+ }
+ return false;
+}
+
+static void BKE_fluid_modifier_freeDomain(FluidModifierData *mmd)
+{
+ if (mmd->domain) {
+ if (mmd->domain->fluid) {
+ manta_free(mmd->domain->fluid);
+ }
+
+ if (mmd->domain->fluid_mutex) {
+ BLI_rw_mutex_free(mmd->domain->fluid_mutex);
+ }
+
+ if (mmd->domain->effector_weights) {
+ MEM_freeN(mmd->domain->effector_weights);
+ }
+ mmd->domain->effector_weights = NULL;
+
+ if (!(mmd->modifier.flag & eModifierFlag_SharedCaches)) {
+ BKE_ptcache_free_list(&(mmd->domain->ptcaches[0]));
+ mmd->domain->point_cache[0] = NULL;
+ }
+
+ if (mmd->domain->mesh_velocities) {
+ MEM_freeN(mmd->domain->mesh_velocities);
+ }
+ mmd->domain->mesh_velocities = NULL;
+
+ if (mmd->domain->coba) {
+ MEM_freeN(mmd->domain->coba);
+ }
+
+ MEM_freeN(mmd->domain);
+ mmd->domain = NULL;
+ }
+}
+
+static void BKE_fluid_modifier_freeFlow(FluidModifierData *mmd)
+{
+ if (mmd->flow) {
+ if (mmd->flow->mesh) {
+ BKE_id_free(NULL, mmd->flow->mesh);
+ }
+ mmd->flow->mesh = NULL;
+
+ if (mmd->flow->verts_old) {
+ MEM_freeN(mmd->flow->verts_old);
+ }
+ mmd->flow->verts_old = NULL;
+ mmd->flow->numverts = 0;
+
+ MEM_freeN(mmd->flow);
+ mmd->flow = NULL;
+ }
+}
+
+static void BKE_fluid_modifier_freeEffector(FluidModifierData *mmd)
+{
+ if (mmd->effector) {
+ if (mmd->effector->mesh) {
+ BKE_id_free(NULL, mmd->effector->mesh);
+ }
+ mmd->effector->mesh = NULL;
+
+ if (mmd->effector->verts_old) {
+ MEM_freeN(mmd->effector->verts_old);
+ }
+ mmd->effector->verts_old = NULL;
+ mmd->effector->numverts = 0;
+
+ MEM_freeN(mmd->effector);
+ mmd->effector = NULL;
+ }
+}
+
+static void BKE_fluid_modifier_reset_ex(struct FluidModifierData *mmd, bool need_lock)
+{
+ if (!mmd) {
+ return;
+ }
+
+ if (mmd->domain) {
+ if (mmd->domain->fluid) {
+ if (need_lock) {
+ BLI_rw_mutex_lock(mmd->domain->fluid_mutex, THREAD_LOCK_WRITE);
+ }
+
+ manta_free(mmd->domain->fluid);
+ mmd->domain->fluid = NULL;
+
+ if (need_lock) {
+ BLI_rw_mutex_unlock(mmd->domain->fluid_mutex);
+ }
+ }
+
+ mmd->time = -1;
+ mmd->domain->total_cells = 0;
+ mmd->domain->active_fields = 0;
+ }
+ else if (mmd->flow) {
+ if (mmd->flow->verts_old) {
+ MEM_freeN(mmd->flow->verts_old);
+ }
+ mmd->flow->verts_old = NULL;
+ mmd->flow->numverts = 0;
+ }
+ else if (mmd->effector) {
+ if (mmd->effector->verts_old) {
+ MEM_freeN(mmd->effector->verts_old);
+ }
+ mmd->effector->verts_old = NULL;
+ mmd->effector->numverts = 0;
+ }
+}
+
+void BKE_fluid_modifier_reset(struct FluidModifierData *mmd)
+{
+ BKE_fluid_modifier_reset_ex(mmd, true);
+}
+
+void BKE_fluid_modifier_free(FluidModifierData *mmd)
+{
+ if (!mmd) {
+ return;
+ }
+
+ BKE_fluid_modifier_freeDomain(mmd);
+ BKE_fluid_modifier_freeFlow(mmd);
+ BKE_fluid_modifier_freeEffector(mmd);
+}
+
+void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd)
+{
+ if (!mmd) {
+ return;
+ }
+
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ if (mmd->domain) {
+ BKE_fluid_modifier_freeDomain(mmd);
+ }
+
+ /* domain object data */
+ mmd->domain = MEM_callocN(sizeof(FluidDomainSettings), "FluidDomain");
+ mmd->domain->mmd = mmd;
+ mmd->domain->effector_weights = BKE_effector_add_weights(NULL);
+ mmd->domain->fluid = NULL;
+ mmd->domain->fluid_mutex = BLI_rw_mutex_alloc();
+ mmd->domain->force_group = NULL;
+ mmd->domain->fluid_group = NULL;
+ mmd->domain->effector_group = NULL;
+
+ /* adaptive domain options */
+ mmd->domain->adapt_margin = 4;
+ mmd->domain->adapt_res = 0;
+ mmd->domain->adapt_threshold = 0.02f;
+
+ /* fluid domain options */
+ mmd->domain->maxres = 64;
+ mmd->domain->solver_res = 3;
+ mmd->domain->border_collisions = 0; // open domain
+ mmd->domain->flags = FLUID_DOMAIN_USE_DISSOLVE_LOG | FLUID_DOMAIN_USE_ADAPTIVE_TIME;
+ mmd->domain->gravity[0] = 0.0f;
+ mmd->domain->gravity[1] = 0.0f;
+ mmd->domain->gravity[2] = -1.0f;
+ mmd->domain->active_fields = 0;
+ mmd->domain->type = FLUID_DOMAIN_TYPE_GAS;
+ mmd->domain->boundary_width = 1;
+
+ /* smoke domain options */
+ mmd->domain->alpha = 1.0f;
+ mmd->domain->beta = 1.0f;
+ mmd->domain->diss_speed = 5;
+ mmd->domain->vorticity = 0;
+ mmd->domain->active_color[0] = 0.0f;
+ mmd->domain->active_color[1] = 0.0f;
+ mmd->domain->active_color[2] = 0.0f;
+ mmd->domain->highres_sampling = SM_HRES_FULLSAMPLE;
+
+ /* flame options */
+ mmd->domain->burning_rate = 0.75f;
+ mmd->domain->flame_smoke = 1.0f;
+ mmd->domain->flame_vorticity = 0.5f;
+ mmd->domain->flame_ignition = 1.5f;
+ mmd->domain->flame_max_temp = 3.0f;
+ mmd->domain->flame_smoke_color[0] = 0.7f;
+ mmd->domain->flame_smoke_color[1] = 0.7f;
+ mmd->domain->flame_smoke_color[2] = 0.7f;
+
+ /* noise options */
+ mmd->domain->noise_strength = 1.0;
+ mmd->domain->noise_pos_scale = 2.0f;
+ mmd->domain->noise_time_anim = 0.1f;
+ mmd->domain->noise_scale = 2;
+ mmd->domain->noise_type = FLUID_NOISE_TYPE_WAVELET;
+
+ /* liquid domain options */
+ mmd->domain->simulation_method = FLUID_DOMAIN_METHOD_FLIP;
+ mmd->domain->flip_ratio = 0.97f;
+ mmd->domain->particle_randomness = 0.1f;
+ mmd->domain->particle_number = 2;
+ mmd->domain->particle_minimum = 8;
+ mmd->domain->particle_maximum = 16;
+ mmd->domain->particle_radius = 1.5f;
+ mmd->domain->particle_band_width = 3.0f;
+ mmd->domain->fractions_threshold = 0.05f;
+
+ /* diffusion options*/
+ mmd->domain->surface_tension = 0.0f;
+ mmd->domain->viscosity_base = 1.0f;
+ mmd->domain->viscosity_exponent = 6.0f;
+ mmd->domain->domain_size = 0.5f;
+
+ /* mesh options */
+ mmd->domain->mesh_velocities = NULL;
+ mmd->domain->mesh_concave_upper = 3.5f;
+ mmd->domain->mesh_concave_lower = 0.4f;
+ mmd->domain->mesh_particle_radius = 2.0;
+ mmd->domain->mesh_smoothen_pos = 1;
+ mmd->domain->mesh_smoothen_neg = 1;
+ mmd->domain->mesh_scale = 2;
+ mmd->domain->totvert = 0;
+ mmd->domain->mesh_generator = FLUID_DOMAIN_MESH_IMPROVED;
+
+ /* secondary particle options */
+ mmd->domain->sndparticle_tau_min_wc = 2.0;
+ mmd->domain->sndparticle_tau_max_wc = 8.0;
+ mmd->domain->sndparticle_tau_min_ta = 5.0;
+ mmd->domain->sndparticle_tau_max_ta = 20.0;
+ mmd->domain->sndparticle_tau_min_k = 1.0;
+ mmd->domain->sndparticle_tau_max_k = 5.0;
+ mmd->domain->sndparticle_k_wc = 200;
+ mmd->domain->sndparticle_k_ta = 40;
+ mmd->domain->sndparticle_k_b = 0.5;
+ mmd->domain->sndparticle_k_d = 0.6;
+ mmd->domain->sndparticle_l_min = 10.0;
+ mmd->domain->sndparticle_l_max = 25.0;
+ mmd->domain->sndparticle_boundary = SNDPARTICLE_BOUNDARY_DELETE;
+ mmd->domain->sndparticle_combined_export = SNDPARTICLE_COMBINED_EXPORT_OFF;
+ mmd->domain->sndparticle_potential_radius = 2;
+ mmd->domain->sndparticle_update_radius = 2;
+ mmd->domain->particle_type = 0;
+ mmd->domain->particle_scale = 1;
+
+ /* fluid guide options */
+ mmd->domain->guide_parent = NULL;
+ mmd->domain->guide_alpha = 2.0f;
+ mmd->domain->guide_beta = 5;
+ mmd->domain->guide_vel_factor = 2.0f;
+ mmd->domain->guide_source = FLUID_DOMAIN_GUIDE_SRC_DOMAIN;
+
+ /* cache options */
+ mmd->domain->cache_frame_start = 1;
+ mmd->domain->cache_frame_end = 50;
+ mmd->domain->cache_frame_pause_data = 0;
+ mmd->domain->cache_frame_pause_noise = 0;
+ mmd->domain->cache_frame_pause_mesh = 0;
+ mmd->domain->cache_frame_pause_particles = 0;
+ mmd->domain->cache_frame_pause_guide = 0;
+ mmd->domain->cache_flag = 0;
+ mmd->domain->cache_type = FLUID_DOMAIN_CACHE_MODULAR;
+ mmd->domain->cache_mesh_format = FLUID_DOMAIN_FILE_BIN_OBJECT;
+ mmd->domain->cache_data_format = FLUID_DOMAIN_FILE_UNI;
+ mmd->domain->cache_particle_format = FLUID_DOMAIN_FILE_UNI;
+ mmd->domain->cache_noise_format = FLUID_DOMAIN_FILE_UNI;
+ modifier_path_init(mmd->domain->cache_directory,
+ sizeof(mmd->domain->cache_directory),
+ FLUID_DOMAIN_DIR_DEFAULT);
+
+ /* time options */
+ mmd->domain->time_scale = 1.0;
+ mmd->domain->cfl_condition = 4.0;
+ mmd->domain->timesteps_minimum = 1;
+ mmd->domain->timesteps_maximum = 4;
+
+ /* display options */
+ mmd->domain->slice_method = FLUID_DOMAIN_SLICE_VIEW_ALIGNED;
+ mmd->domain->axis_slice_method = AXIS_SLICE_FULL;
+ mmd->domain->slice_axis = 0;
+ mmd->domain->interp_method = 0;
+ mmd->domain->draw_velocity = false;
+ mmd->domain->slice_per_voxel = 5.0f;
+ mmd->domain->slice_depth = 0.5f;
+ mmd->domain->display_thickness = 1.0f;
+ mmd->domain->coba = NULL;
+ mmd->domain->vector_scale = 1.0f;
+ mmd->domain->vector_draw_type = VECTOR_DRAW_NEEDLE;
+ mmd->domain->use_coba = false;
+ mmd->domain->coba_field = FLUID_DOMAIN_FIELD_DENSITY;
+
+ /* -- Deprecated / unsed options (below)-- */
+
+ /* pointcache options */
+ BLI_listbase_clear(&mmd->domain->ptcaches[1]);
+ mmd->domain->point_cache[0] = BKE_ptcache_add(&(mmd->domain->ptcaches[0]));
+ mmd->domain->point_cache[0]->flag |= PTCACHE_DISK_CACHE;
+ mmd->domain->point_cache[0]->step = 1;
+ mmd->domain->point_cache[1] = NULL; /* Deprecated */
+ mmd->domain->cache_comp = SM_CACHE_LIGHT;
+ mmd->domain->cache_high_comp = SM_CACHE_LIGHT;
+
+ /* OpenVDB cache options */
+# ifdef WITH_OPENVDB_BLOSC
+ mmd->domain->openvdb_comp = VDB_COMPRESSION_BLOSC;
+# else
+ mmd->domain->openvdb_comp = VDB_COMPRESSION_ZIP;
+# endif
+ mmd->domain->clipping = 1e-3f;
+ mmd->domain->data_depth = 0;
+ }
+ else if (mmd->type & MOD_FLUID_TYPE_FLOW) {
+ if (mmd->flow) {
+ BKE_fluid_modifier_freeFlow(mmd);
+ }
+
+ /* flow object data */
+ mmd->flow = MEM_callocN(sizeof(FluidFlowSettings), "MantaFlow");
+ mmd->flow->mmd = mmd;
+ mmd->flow->mesh = NULL;
+ mmd->flow->psys = NULL;
+ mmd->flow->noise_texture = NULL;
+
+ /* initial velocity */
+ mmd->flow->verts_old = NULL;
+ mmd->flow->numverts = 0;
+ mmd->flow->vel_multi = 1.0f;
+ mmd->flow->vel_normal = 0.0f;
+ mmd->flow->vel_random = 0.0f;
+ mmd->flow->vel_coord[0] = 0.0f;
+ mmd->flow->vel_coord[1] = 0.0f;
+ mmd->flow->vel_coord[2] = 0.0f;
+
+ /* emission */
+ mmd->flow->density = 1.0f;
+ mmd->flow->color[0] = 0.7f;
+ mmd->flow->color[1] = 0.7f;
+ mmd->flow->color[2] = 0.7f;
+ mmd->flow->fuel_amount = 1.0f;
+ mmd->flow->temperature = 1.0f;
+ mmd->flow->volume_density = 0.0f;
+ mmd->flow->surface_distance = 1.5f;
+ mmd->flow->particle_size = 1.0f;
+ mmd->flow->subframes = 0;
+
+ /* texture control */
+ mmd->flow->source = FLUID_FLOW_SOURCE_MESH;
+ mmd->flow->texture_size = 1.0f;
+
+ mmd->flow->type = FLUID_FLOW_TYPE_SMOKE;
+ mmd->flow->behavior = FLUID_FLOW_BEHAVIOR_GEOMETRY;
+ mmd->flow->type = FLUID_FLOW_TYPE_SMOKE;
+ mmd->flow->flags = FLUID_FLOW_ABSOLUTE | FLUID_FLOW_USE_PART_SIZE | FLUID_FLOW_USE_INFLOW;
+ }
+ else if (mmd->type & MOD_FLUID_TYPE_EFFEC) {
+ if (mmd->effector) {
+ BKE_fluid_modifier_freeEffector(mmd);
+ }
+
+ /* effector object data */
+ mmd->effector = MEM_callocN(sizeof(FluidEffectorSettings), "MantaEffector");
+ mmd->effector->mmd = mmd;
+ mmd->effector->mesh = NULL;
+ mmd->effector->verts_old = NULL;
+ mmd->effector->numverts = 0;
+ mmd->effector->surface_distance = 0.0f;
+ mmd->effector->type = FLUID_EFFECTOR_TYPE_COLLISION;
+ mmd->effector->flags = 0;
+
+ /* guide options */
+ mmd->effector->guide_mode = FLUID_EFFECTOR_GUIDE_MAX;
+ mmd->effector->vel_multi = 1.0f;
+ }
+}
+
+void BKE_fluid_modifier_copy(const struct FluidModifierData *mmd,
+ struct FluidModifierData *tmmd,
+ const int flag)
+{
+ tmmd->type = mmd->type;
+ tmmd->time = mmd->time;
+
+ BKE_fluid_modifier_create_type_data(tmmd);
+
+ if (tmmd->domain) {
+ FluidDomainSettings *tmds = tmmd->domain;
+ FluidDomainSettings *mds = mmd->domain;
+
+ /* domain object data */
+ tmds->fluid_group = mds->fluid_group;
+ tmds->force_group = mds->force_group;
+ tmds->effector_group = mds->effector_group;
+ if (tmds->effector_weights) {
+ MEM_freeN(tmds->effector_weights);
+ }
+ tmds->effector_weights = MEM_dupallocN(mds->effector_weights);
+
+ /* adaptive domain options */
+ tmds->adapt_margin = mds->adapt_margin;
+ tmds->adapt_res = mds->adapt_res;
+ tmds->adapt_threshold = mds->adapt_threshold;
+
+ /* fluid domain options */
+ tmds->maxres = mds->maxres;
+ tmds->solver_res = mds->solver_res;
+ tmds->border_collisions = mds->border_collisions;
+ tmds->flags = mds->flags;
+ tmds->gravity[0] = mds->gravity[0];
+ tmds->gravity[1] = mds->gravity[1];
+ tmds->gravity[2] = mds->gravity[2];
+ tmds->active_fields = mds->active_fields;
+ tmds->type = mds->type;
+ tmds->boundary_width = mds->boundary_width;
+
+ /* smoke domain options */
+ tmds->alpha = mds->alpha;
+ tmds->beta = mds->beta;
+ tmds->diss_speed = mds->diss_speed;
+ tmds->vorticity = mds->vorticity;
+ tmds->highres_sampling = mds->highres_sampling;
+
+ /* flame options */
+ tmds->burning_rate = mds->burning_rate;
+ tmds->flame_smoke = mds->flame_smoke;
+ tmds->flame_vorticity = mds->flame_vorticity;
+ tmds->flame_ignition = mds->flame_ignition;
+ tmds->flame_max_temp = mds->flame_max_temp;
+ copy_v3_v3(tmds->flame_smoke_color, mds->flame_smoke_color);
+
+ /* noise options */
+ tmds->noise_strength = mds->noise_strength;
+ tmds->noise_pos_scale = mds->noise_pos_scale;
+ tmds->noise_time_anim = mds->noise_time_anim;
+ tmds->noise_scale = mds->noise_scale;
+ tmds->noise_type = mds->noise_type;
+
+ /* liquid domain options */
+ tmds->flip_ratio = mds->flip_ratio;
+ tmds->particle_randomness = mds->particle_randomness;
+ tmds->particle_number = mds->particle_number;
+ tmds->particle_minimum = mds->particle_minimum;
+ tmds->particle_maximum = mds->particle_maximum;
+ tmds->particle_radius = mds->particle_radius;
+ tmds->particle_band_width = mds->particle_band_width;
+ tmds->fractions_threshold = mds->fractions_threshold;
+
+ /* diffusion options*/
+ tmds->surface_tension = mds->surface_tension;
+ tmds->viscosity_base = mds->viscosity_base;
+ tmds->viscosity_exponent = mds->viscosity_exponent;
+ tmds->domain_size = mds->domain_size;
+
+ /* mesh options */
+ if (mds->mesh_velocities) {
+ tmds->mesh_velocities = MEM_dupallocN(mds->mesh_velocities);
+ }
+ tmds->mesh_concave_upper = mds->mesh_concave_upper;
+ tmds->mesh_concave_lower = mds->mesh_concave_lower;
+ tmds->mesh_particle_radius = mds->mesh_particle_radius;
+ tmds->mesh_smoothen_pos = mds->mesh_smoothen_pos;
+ tmds->mesh_smoothen_neg = mds->mesh_smoothen_neg;
+ tmds->mesh_scale = mds->mesh_scale;
+ tmds->totvert = mds->totvert;
+ tmds->mesh_generator = mds->mesh_generator;
+
+ /* secondary particle options */
+ tmds->sndparticle_k_b = mds->sndparticle_k_b;
+ tmds->sndparticle_k_d = mds->sndparticle_k_d;
+ tmds->sndparticle_k_ta = mds->sndparticle_k_ta;
+ tmds->sndparticle_k_wc = mds->sndparticle_k_wc;
+ tmds->sndparticle_l_max = mds->sndparticle_l_max;
+ tmds->sndparticle_l_min = mds->sndparticle_l_min;
+ tmds->sndparticle_tau_max_k = mds->sndparticle_tau_max_k;
+ tmds->sndparticle_tau_max_ta = mds->sndparticle_tau_max_ta;
+ tmds->sndparticle_tau_max_wc = mds->sndparticle_tau_max_wc;
+ tmds->sndparticle_tau_min_k = mds->sndparticle_tau_min_k;
+ tmds->sndparticle_tau_min_ta = mds->sndparticle_tau_min_ta;
+ tmds->sndparticle_tau_min_wc = mds->sndparticle_tau_min_wc;
+ tmds->sndparticle_boundary = mds->sndparticle_boundary;
+ tmds->sndparticle_combined_export = mds->sndparticle_combined_export;
+ tmds->sndparticle_potential_radius = mds->sndparticle_potential_radius;
+ tmds->sndparticle_update_radius = mds->sndparticle_update_radius;
+ tmds->particle_type = mds->particle_type;
+ tmds->particle_scale = mds->particle_scale;
+
+ /* fluid guide options */
+ tmds->guide_parent = mds->guide_parent;
+ tmds->guide_alpha = mds->guide_alpha;
+ tmds->guide_beta = mds->guide_beta;
+ tmds->guide_vel_factor = mds->guide_vel_factor;
+ copy_v3_v3_int(tmds->guide_res, mds->guide_res);
+ tmds->guide_source = mds->guide_source;
+
+ /* cache options */
+ tmds->cache_frame_start = mds->cache_frame_start;
+ tmds->cache_frame_end = mds->cache_frame_end;
+ tmds->cache_frame_pause_data = mds->cache_frame_pause_data;
+ tmds->cache_frame_pause_noise = mds->cache_frame_pause_noise;
+ tmds->cache_frame_pause_mesh = mds->cache_frame_pause_mesh;
+ tmds->cache_frame_pause_particles = mds->cache_frame_pause_particles;
+ tmds->cache_frame_pause_guide = mds->cache_frame_pause_guide;
+ tmds->cache_flag = mds->cache_flag;
+ tmds->cache_type = mds->cache_type;
+ tmds->cache_mesh_format = mds->cache_mesh_format;
+ tmds->cache_data_format = mds->cache_data_format;
+ tmds->cache_particle_format = mds->cache_particle_format;
+ tmds->cache_noise_format = mds->cache_noise_format;
+ BLI_strncpy(tmds->cache_directory, mds->cache_directory, sizeof(tmds->cache_directory));
+
+ /* time options */
+ tmds->time_scale = mds->time_scale;
+ tmds->cfl_condition = mds->cfl_condition;
+ tmds->timesteps_minimum = mds->timesteps_minimum;
+ tmds->timesteps_maximum = mds->timesteps_maximum;
+
+ /* display options */
+ tmds->slice_method = mds->slice_method;
+ tmds->axis_slice_method = mds->axis_slice_method;
+ tmds->slice_axis = mds->slice_axis;
+ tmds->interp_method = mds->interp_method;
+ tmds->draw_velocity = mds->draw_velocity;
+ tmds->slice_per_voxel = mds->slice_per_voxel;
+ tmds->slice_depth = mds->slice_depth;
+ tmds->display_thickness = mds->display_thickness;
+ if (mds->coba) {
+ tmds->coba = MEM_dupallocN(mds->coba);
+ }
+ tmds->vector_scale = mds->vector_scale;
+ tmds->vector_draw_type = mds->vector_draw_type;
+ tmds->use_coba = mds->use_coba;
+ tmds->coba_field = mds->coba_field;
+
+ /* -- Deprecated / unsed options (below)-- */
+
+ /* pointcache options */
+ BKE_ptcache_free_list(&(tmds->ptcaches[0]));
+ if (flag & LIB_ID_CREATE_NO_MAIN) {
+ /* Share the cache with the original object's modifier. */
+ tmmd->modifier.flag |= eModifierFlag_SharedCaches;
+ tmds->point_cache[0] = mds->point_cache[0];
+ tmds->ptcaches[0] = mds->ptcaches[0];
+ }
+ else {
+ tmds->point_cache[0] = BKE_ptcache_copy_list(
+ &(tmds->ptcaches[0]), &(mds->ptcaches[0]), flag);
+ }
+
+ /* OpenVDB cache options */
+ tmds->openvdb_comp = mds->openvdb_comp;
+ tmds->clipping = mds->clipping;
+ tmds->data_depth = mds->data_depth;
+ }
+ else if (tmmd->flow) {
+ FluidFlowSettings *tmfs = tmmd->flow;
+ FluidFlowSettings *mfs = mmd->flow;
+
+ tmfs->psys = mfs->psys;
+ tmfs->noise_texture = mfs->noise_texture;
+
+ /* initial velocity */
+ tmfs->vel_multi = mfs->vel_multi;
+ tmfs->vel_normal = mfs->vel_normal;
+ tmfs->vel_random = mfs->vel_random;
+ tmfs->vel_coord[0] = mfs->vel_coord[0];
+ tmfs->vel_coord[1] = mfs->vel_coord[1];
+ tmfs->vel_coord[2] = mfs->vel_coord[2];
+
+ /* emission */
+ tmfs->density = mfs->density;
+ copy_v3_v3(tmfs->color, mfs->color);
+ tmfs->fuel_amount = mfs->fuel_amount;
+ tmfs->temperature = mfs->temperature;
+ tmfs->volume_density = mfs->volume_density;
+ tmfs->surface_distance = mfs->surface_distance;
+ tmfs->particle_size = mfs->particle_size;
+ tmfs->subframes = mfs->subframes;
+
+ /* texture control */
+ tmfs->texture_size = mfs->texture_size;
+ tmfs->texture_offset = mfs->texture_offset;
+ BLI_strncpy(tmfs->uvlayer_name, mfs->uvlayer_name, sizeof(tmfs->uvlayer_name));
+ tmfs->vgroup_density = mfs->vgroup_density;
+
+ tmfs->type = mfs->type;
+ tmfs->behavior = mfs->behavior;
+ tmfs->source = mfs->source;
+ tmfs->texture_type = mfs->texture_type;
+ tmfs->flags = mfs->flags;
+ }
+ else if (tmmd->effector) {
+ FluidEffectorSettings *tmes = tmmd->effector;
+ FluidEffectorSettings *mes = mmd->effector;
+
+ tmes->surface_distance = mes->surface_distance;
+ tmes->type = mes->type;
+
+ /* guide options */
+ tmes->guide_mode = mes->guide_mode;
+ tmes->vel_multi = mes->vel_multi;
+ }
+}
+
+// forward declaration
+static void manta_smoke_calc_transparency(FluidDomainSettings *mds, ViewLayer *view_layer);
+static float calc_voxel_transp(
+ float *result, float *input, int res[3], int *pixel, float *t_ray, float correct);
+static void update_mesh_distances(int index,
+ float *mesh_distances,
+ BVHTreeFromMesh *tree_data,
+ const float ray_start[3],
+ float surface_thickness,
+ int use_plane_init);
+
+static int get_light(ViewLayer *view_layer, float *light)
+{
+ Base *base_tmp = NULL;
+ int found_light = 0;
+
+ // try to find a lamp, preferably local
+ for (base_tmp = FIRSTBASE(view_layer); base_tmp; base_tmp = base_tmp->next) {
+ if (base_tmp->object->type == OB_LAMP) {
+ Light *la = base_tmp->object->data;
+
+ if (la->type == LA_LOCAL) {
+ copy_v3_v3(light, base_tmp->object->obmat[3]);
+ return 1;
+ }
+ else if (!found_light) {
+ copy_v3_v3(light, base_tmp->object->obmat[3]);
+ found_light = 1;
+ }
+ }
+ }
+
+ return found_light;
+}
+
+/**********************************************************
+ * Obstacles
+ **********************************************************/
+
+typedef struct ObstaclesFromDMData {
+ FluidDomainSettings *mds;
+ FluidEffectorSettings *mes;
+ const MVert *mvert;
+ const MLoop *mloop;
+ const MLoopTri *looptri;
+ BVHTreeFromMesh *tree;
+
+ bool has_velocity;
+ float *vert_vel;
+ float *velocity_x, *velocity_y, *velocity_z;
+ int *num_objects;
+ float *distances_map;
+} ObstaclesFromDMData;
+
+static void obstacles_from_mesh_task_cb(void *__restrict userdata,
+ const int z,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ ObstaclesFromDMData *data = userdata;
+ FluidDomainSettings *mds = data->mds;
+
+ /* slightly rounded-up sqrt(3 * (0.5)^2) == max. distance of cell boundary along the diagonal */
+ const float surface_distance = 2.0f; // 0.867f;
+ /* Note: Use larger surface distance to cover larger area with obvel. Manta will use these obvels
+ * and extrapolate them (inside and outside obstacle) */
+
+ for (int x = mds->res_min[0]; x < mds->res_max[0]; x++) {
+ for (int y = mds->res_min[1]; y < mds->res_max[1]; y++) {
+ const int index = manta_get_index(
+ x - mds->res_min[0], mds->res[0], y - mds->res_min[1], mds->res[1], z - mds->res_min[2]);
+
+ float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f};
+ BVHTreeNearest nearest = {0};
+ nearest.index = -1;
+ nearest.dist_sq = surface_distance *
+ surface_distance; /* find_nearest uses squared distance */
+ bool has_inc_obj = false;
+
+ /* find the nearest point on the mesh */
+ if (BLI_bvhtree_find_nearest(
+ data->tree->tree, ray_start, &nearest, data->tree->nearest_callback, data->tree) !=
+ -1) {
+ const MLoopTri *lt = &data->looptri[nearest.index];
+ float weights[3];
+ int v1, v2, v3;
+
+ /* calculate barycentric weights for nearest point */
+ v1 = data->mloop[lt->tri[0]].v;
+ v2 = data->mloop[lt->tri[1]].v;
+ v3 = data->mloop[lt->tri[2]].v;
+ interp_weights_tri_v3(
+ weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, nearest.co);
+
+ if (data->has_velocity) {
+ /* increase object count */
+ data->num_objects[index]++;
+ has_inc_obj = true;
+
+ /* apply object velocity */
+ float hit_vel[3];
+ interp_v3_v3v3v3(hit_vel,
+ &data->vert_vel[v1 * 3],
+ &data->vert_vel[v2 * 3],
+ &data->vert_vel[v3 * 3],
+ weights);
+
+ /* Guiding has additional velocity multiplier */
+ if (data->mes->type == FLUID_EFFECTOR_TYPE_GUIDE) {
+ mul_v3_fl(hit_vel, data->mes->vel_multi);
+
+ switch (data->mes->guide_mode) {
+ case FLUID_EFFECTOR_GUIDE_AVERAGED:
+ data->velocity_x[index] = (data->velocity_x[index] + hit_vel[0]) * 0.5f;
+ data->velocity_y[index] = (data->velocity_y[index] + hit_vel[1]) * 0.5f;
+ data->velocity_z[index] = (data->velocity_z[index] + hit_vel[2]) * 0.5f;
+ break;
+ case FLUID_EFFECTOR_GUIDE_OVERRIDE:
+ data->velocity_x[index] = hit_vel[0];
+ data->velocity_y[index] = hit_vel[1];
+ data->velocity_z[index] = hit_vel[2];
+ break;
+ case FLUID_EFFECTOR_GUIDE_MIN:
+ data->velocity_x[index] = MIN2(fabsf(hit_vel[0]), fabsf(data->velocity_x[index]));
+ data->velocity_y[index] = MIN2(fabsf(hit_vel[1]), fabsf(data->velocity_y[index]));
+ data->velocity_z[index] = MIN2(fabsf(hit_vel[2]), fabsf(data->velocity_z[index]));
+ break;
+ case FLUID_EFFECTOR_GUIDE_MAX:
+ default:
+ data->velocity_x[index] = MAX2(fabsf(hit_vel[0]), fabsf(data->velocity_x[index]));
+ data->velocity_y[index] = MAX2(fabsf(hit_vel[1]), fabsf(data->velocity_y[index]));
+ data->velocity_z[index] = MAX2(fabsf(hit_vel[2]), fabsf(data->velocity_z[index]));
+ break;
+ }
+ }
+ else {
+ /* Apply (i.e. add) effector object velocity */
+ data->velocity_x[index] += (data->mes->type == FLUID_EFFECTOR_TYPE_GUIDE) ?
+ hit_vel[0] * data->mes->vel_multi :
+ hit_vel[0];
+ data->velocity_y[index] += (data->mes->type == FLUID_EFFECTOR_TYPE_GUIDE) ?
+ hit_vel[1] * data->mes->vel_multi :
+ hit_vel[1];
+ data->velocity_z[index] += (data->mes->type == FLUID_EFFECTOR_TYPE_GUIDE) ?
+ hit_vel[2] * data->mes->vel_multi :
+ hit_vel[2];
+# ifdef DEBUG_PRINT
+ /* Debugging: Print object velocities. */
+ printf("adding effector object vel: [%f, %f, %f], dx is: %f\n",
+ hit_vel[0],
+ hit_vel[1],
+ hit_vel[2],
+ mds->dx);
+# endif
+ }
+ }
+ }
+
+ /* Get distance to mesh surface from both within and outside grid (mantaflow phi grid). */
+ if (data->distances_map) {
+ update_mesh_distances(index,
+ data->distances_map,
+ data->tree,
+ ray_start,
+ data->mes->surface_distance,
+ data->mes->flags & FLUID_FLOW_USE_PLANE_INIT);
+
+ /* Ensure that num objects are also counted inside object.
+ * But don't count twice (see object inc for nearest point). */
+ if (data->distances_map[index] < 0 && !has_inc_obj) {
+ data->num_objects[index]++;
+ }
+ }
+ }
+ }
+}
+
+static void obstacles_from_mesh(Object *coll_ob,
+ FluidDomainSettings *mds,
+ FluidEffectorSettings *mes,
+ float *distances_map,
+ float *velocity_x,
+ float *velocity_y,
+ float *velocity_z,
+ int *num_objects,
+ float dt)
+{
+ if (!mes->mesh) {
+ return;
+ }
+ {
+ Mesh *me = NULL;
+ MVert *mvert = NULL;
+ const MLoopTri *looptri;
+ const MLoop *mloop;
+ BVHTreeFromMesh tree_data = {NULL};
+ int numverts, i;
+
+ float *vert_vel = NULL;
+ bool has_velocity = false;
+
+ me = BKE_mesh_copy_for_eval(mes->mesh, true);
+
+ /* Duplicate vertices to modify. */
+ if (me->mvert) {
+ me->mvert = MEM_dupallocN(me->mvert);
+ CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
+ }
+
+ BKE_mesh_ensure_normals(me);
+ mvert = me->mvert;
+ mloop = me->mloop;
+ looptri = BKE_mesh_runtime_looptri_ensure(me);
+ numverts = me->totvert;
+
+ /* TODO (sebbas):
+ * Make vert_vel init optional?
+ * code is in trouble if the object moves but is declared as "does not move" */
+ {
+ vert_vel = MEM_callocN(sizeof(float) * numverts * 3, "manta_obs_velocity");
+
+ if (mes->numverts != numverts || !mes->verts_old) {
+ if (mes->verts_old) {
+ MEM_freeN(mes->verts_old);
+ }
+
+ mes->verts_old = MEM_callocN(sizeof(float) * numverts * 3, "manta_obs_verts_old");
+ mes->numverts = numverts;
+ }
+ else {
+ has_velocity = true;
+ }
+ }
+
+ /* Transform collider vertices to
+ * domain grid space for fast lookups */
+ for (i = 0; i < numverts; i++) {
+ float n[3];
+ float co[3];
+
+ /* vert pos */
+ mul_m4_v3(coll_ob->obmat, mvert[i].co);
+ manta_pos_to_cell(mds, mvert[i].co);
+
+ /* vert normal */
+ normal_short_to_float_v3(n, mvert[i].no);
+ mul_mat3_m4_v3(coll_ob->obmat, n);
+ mul_mat3_m4_v3(mds->imat, n);
+ normalize_v3(n);
+ normal_float_to_short_v3(mvert[i].no, n);
+
+ /* vert velocity */
+ add_v3fl_v3fl_v3i(co, mvert[i].co, mds->shift);
+ if (has_velocity) {
+ sub_v3_v3v3(&vert_vel[i * 3], co, &mes->verts_old[i * 3]);
+ mul_v3_fl(&vert_vel[i * 3], mds->dx / dt);
+ }
+ copy_v3_v3(&mes->verts_old[i * 3], co);
+ }
+
+ if (BKE_bvhtree_from_mesh_get(&tree_data, me, BVHTREE_FROM_LOOPTRI, 4)) {
+ ObstaclesFromDMData data = {.mds = mds,
+ .mes = mes,
+ .mvert = mvert,
+ .mloop = mloop,
+ .looptri = looptri,
+ .tree = &tree_data,
+ .has_velocity = has_velocity,
+ .vert_vel = vert_vel,
+ .velocity_x = velocity_x,
+ .velocity_y = velocity_y,
+ .velocity_z = velocity_z,
+ .num_objects = num_objects,
+ .distances_map = distances_map};
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 2;
+ BLI_task_parallel_range(
+ mds->res_min[2], mds->res_max[2], &data, obstacles_from_mesh_task_cb, &settings);
+ }
+ /* free bvh tree */
+ free_bvhtree_from_mesh(&tree_data);
+
+ if (vert_vel) {
+ MEM_freeN(vert_vel);
+ }
+ if (me->mvert) {
+ MEM_freeN(me->mvert);
+ }
+ BKE_id_free(NULL, me);
+ }
+}
+
+static void update_obstacleflags(FluidDomainSettings *mds,
+ Object **coll_ob_array,
+ int coll_ob_array_len)
+{
+ int active_fields = mds->active_fields;
+ uint coll_index;
+
+ /* First, remove all flags that we want to update. */
+ int prev_flags = (FLUID_DOMAIN_ACTIVE_OBSTACLE | FLUID_DOMAIN_ACTIVE_GUIDE);
+ active_fields &= ~prev_flags;
+
+ /* Monitor active fields based on flow settings */
+ for (coll_index = 0; coll_index < coll_ob_array_len; coll_index++) {
+ Object *coll_ob = coll_ob_array[coll_index];
+ FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(coll_ob,
+ eModifierType_Fluid);
+
+ if ((mmd2->type & MOD_FLUID_TYPE_EFFEC) && mmd2->effector) {
+ FluidEffectorSettings *mes = mmd2->effector;
+ if (!mes) {
+ break;
+ }
+ if (mes->type == FLUID_EFFECTOR_TYPE_COLLISION) {
+ active_fields |= FLUID_DOMAIN_ACTIVE_OBSTACLE;
+ }
+ if (mes->type == FLUID_EFFECTOR_TYPE_GUIDE) {
+ active_fields |= FLUID_DOMAIN_ACTIVE_GUIDE;
+ }
+ }
+ }
+ /* Finally, initialize new data fields if any */
+ if (active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE) {
+ manta_ensure_obstacle(mds->fluid, mds->mmd);
+ }
+ if (active_fields & FLUID_DOMAIN_ACTIVE_GUIDE) {
+ manta_ensure_guiding(mds->fluid, mds->mmd);
+ }
+ mds->active_fields = active_fields;
+}
+
+static void update_obstacles(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ FluidDomainSettings *mds,
+ float time_per_frame,
+ float frame_length,
+ int frame,
+ float dt)
+{
+ Object **coll_ob_array = NULL;
+ uint coll_ob_array_len = 0, coll_index = 0;
+
+ coll_ob_array = BKE_collision_objects_create(
+ depsgraph, ob, mds->effector_group, &coll_ob_array_len, eModifierType_Fluid);
+
+ /* Update all flow related flags and ensure that corresponding grids get initialized. */
+ update_obstacleflags(mds, coll_ob_array, coll_ob_array_len);
+
+ float *vel_x = manta_get_ob_velocity_x(mds->fluid);
+ float *vel_y = manta_get_ob_velocity_y(mds->fluid);
+ float *vel_z = manta_get_ob_velocity_z(mds->fluid);
+ float *vel_x_guide = manta_get_guide_velocity_x(mds->fluid);
+ float *vel_y_guide = manta_get_guide_velocity_y(mds->fluid);
+ float *vel_z_guide = manta_get_guide_velocity_z(mds->fluid);
+ float *vel_x_orig = manta_get_velocity_x(mds->fluid);
+ float *vel_y_orig = manta_get_velocity_y(mds->fluid);
+ float *vel_z_orig = manta_get_velocity_z(mds->fluid);
+ float *density = manta_smoke_get_density(mds->fluid);
+ float *fuel = manta_smoke_get_fuel(mds->fluid);
+ float *flame = manta_smoke_get_flame(mds->fluid);
+ float *r = manta_smoke_get_color_r(mds->fluid);
+ float *g = manta_smoke_get_color_g(mds->fluid);
+ float *b = manta_smoke_get_color_b(mds->fluid);
+ float *phi_obs_in = manta_get_phiobs_in(mds->fluid);
+ float *phi_guide_in = manta_get_phiguide_in(mds->fluid);
+ int *obstacles = manta_smoke_get_obstacle(mds->fluid);
+ int *num_obstacles = manta_get_num_obstacle(mds->fluid);
+ int *num_guides = manta_get_num_guide(mds->fluid);
+ uint z;
+ float tmp = 0;
+
+ /* Grid reset before writing again. */
+ for (z = 0; z < mds->res[0] * mds->res[1] * mds->res[2]; z++) {
+
+ /* Use big value that's not inf to initialize levelset grids. */
+ if (phi_obs_in) {
+ phi_obs_in[z] = FLT_MAX;
+ }
+ if (phi_guide_in) {
+ phi_guide_in[z] = FLT_MAX;
+ }
+ if (num_obstacles) {
+ num_obstacles[z] = 0;
+ }
+ if (num_guides) {
+ num_guides[z] = 0;
+ }
+ if (vel_x && vel_y && vel_z) {
+ vel_x[z] = 0.0f;
+ vel_y[z] = 0.0f;
+ vel_z[z] = 0.0f;
+ }
+ if (vel_x_guide && vel_y_guide && vel_z_guide) {
+ vel_x_guide[z] = 0.0f;
+ vel_y_guide[z] = 0.0f;
+ vel_z_guide[z] = 0.0f;
+ }
+ }
+
+ /* Prepare grids from effector objects. */
+ for (coll_index = 0; coll_index < coll_ob_array_len; coll_index++) {
+ Object *coll_ob = coll_ob_array[coll_index];
+ FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(coll_ob,
+ eModifierType_Fluid);
+
+ /* TODO (sebbas): check if modifier is active? */
+ if ((mmd2->type & MOD_FLUID_TYPE_EFFEC) && mmd2->effector) {
+ FluidEffectorSettings *mes = mmd2->effector;
+
+ /* Length of one frame. If using adaptive stepping, length is smaller than actual frame
+ * length. */
+ float adaptframe_length = time_per_frame / frame_length;
+
+ /* Handle adaptive subframe (ie has subframe fraction). Need to set according scene subframe
+ * parameter. */
+ if (time_per_frame < frame_length) {
+ scene->r.subframe = adaptframe_length;
+ scene->r.cfra = frame - 1;
+ }
+ /* Handle absolute endframe (ie no subframe fraction). Need to set the scene subframe
+ * parameter to 0 and advance current scene frame. */
+ else {
+ scene->r.subframe = 0.0f;
+ scene->r.cfra = frame;
+ }
+# ifdef DEBUG_PRINT
+ /* Debugging: Print subframe information. */
+ printf("effector: frame: %d // scene current frame: %d // scene current subframe: %f\n",
+ frame,
+ scene->r.cfra,
+ scene->r.subframe);
+# endif
+ /* TODO (sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph) as
+ * subframes don't work with the latter yet. */
+ BKE_object_modifier_update_subframe(
+ depsgraph, scene, coll_ob, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid);
+
+ if (mes && (mes->type == FLUID_EFFECTOR_TYPE_COLLISION)) {
+ obstacles_from_mesh(coll_ob, mds, mes, phi_obs_in, vel_x, vel_y, vel_z, num_obstacles, dt);
+ }
+ if (mes && (mes->type == FLUID_EFFECTOR_TYPE_GUIDE)) {
+ obstacles_from_mesh(coll_ob,
+ mds,
+ mes,
+ phi_guide_in,
+ vel_x_guide,
+ vel_y_guide,
+ vel_z_guide,
+ num_guides,
+ dt);
+ }
+ }
+ }
+
+ BKE_collision_objects_free(coll_ob_array);
+
+ /* Obstacle cells should not contain any velocity from the smoke simulation. */
+ for (z = 0; z < mds->res[0] * mds->res[1] * mds->res[2]; z++) {
+ if (obstacles[z] & 2) /* Mantaflow convention: FlagObstacle. */
+ {
+ if (vel_x_orig && vel_y_orig && vel_z_orig) {
+ vel_x_orig[z] = 0.0f;
+ vel_y_orig[z] = 0.0f;
+ vel_z_orig[z] = 0.0f;
+ }
+ if (density) {
+ density[z] = 0.0f;
+ }
+ if (fuel) {
+ fuel[z] = 0.0f;
+ flame[z] = 0.0f;
+ }
+ if (r) {
+ r[z] = 0.0f;
+ g[z] = 0.0f;
+ b[z] = 0.0f;
+ }
+ }
+ /* Average velocities from multiple obstacles in one cell. */
+ if (num_obstacles && num_obstacles[z]) {
+ tmp = 1.0f / num_obstacles[z];
+ vel_x[z] *= tmp;
+ vel_y[z] *= tmp;
+ vel_z[z] *= tmp;
+ }
+ /* Average velocities from multiple guides in one cell. */
+ if (num_guides && num_guides[z]) {
+ tmp = 1.0f / num_guides[z];
+ vel_x_guide[z] *= tmp;
+ vel_y_guide[z] *= tmp;
+ vel_z_guide[z] *= tmp;
+ }
+ }
+}
+
+/**********************************************************
+ * Flow emission code
+ **********************************************************/
+
+typedef struct EmissionMap {
+ float *influence;
+ float *influence_high;
+ float *velocity;
+ float *distances;
+ float *distances_high;
+ int min[3], max[3], res[3];
+ int hmin[3], hmax[3], hres[3];
+ int total_cells, valid;
+} EmissionMap;
+
+static void em_boundInsert(EmissionMap *em, float point[3])
+{
+ int i = 0;
+ if (!em->valid) {
+ for (; i < 3; i++) {
+ em->min[i] = (int)floor(point[i]);
+ em->max[i] = (int)ceil(point[i]);
+ }
+ em->valid = 1;
+ }
+ else {
+ for (; i < 3; i++) {
+ if (point[i] < em->min[i]) {
+ em->min[i] = (int)floor(point[i]);
+ }
+ if (point[i] > em->max[i]) {
+ em->max[i] = (int)ceil(point[i]);
+ }
+ }
+ }
+}
+
+static void clamp_bounds_in_domain(FluidDomainSettings *mds,
+ int min[3],
+ int max[3],
+ float *min_vel,
+ float *max_vel,
+ int margin,
+ float dt)
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ int adapt = (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) ? mds->adapt_res : 0;
+ /* add margin */
+ min[i] -= margin;
+ max[i] += margin;
+
+ /* adapt to velocity */
+ if (min_vel && min_vel[i] < 0.0f) {
+ min[i] += (int)floor(min_vel[i] * dt);
+ }
+ if (max_vel && max_vel[i] > 0.0f) {
+ max[i] += (int)ceil(max_vel[i] * dt);
+ }
+
+ /* clamp within domain max size */
+ CLAMP(min[i], -adapt, mds->base_res[i] + adapt);
+ CLAMP(max[i], -adapt, mds->base_res[i] + adapt);
+ }
+}
+
+static void em_allocateData(EmissionMap *em, bool use_velocity, int hires_mul)
+{
+ int i, res[3];
+
+ for (i = 0; i < 3; i++) {
+ res[i] = em->max[i] - em->min[i];
+ if (res[i] <= 0) {
+ return;
+ }
+ }
+ em->total_cells = res[0] * res[1] * res[2];
+ copy_v3_v3_int(em->res, res);
+
+ em->influence = MEM_calloc_arrayN(em->total_cells, sizeof(float), "manta_flow_influence");
+ if (use_velocity) {
+ em->velocity = MEM_calloc_arrayN(em->total_cells * 3, sizeof(float), "manta_flow_velocity");
+ }
+
+ em->distances = MEM_malloc_arrayN(em->total_cells, sizeof(float), "fluid_flow_distances");
+ /* Initialize to infinity. */
+ memset(em->distances, 0x7f7f7f7f, sizeof(float) * em->total_cells);
+
+ /* Allocate high resolution map if required. */
+ if (hires_mul > 1) {
+ int total_cells_high = em->total_cells * (hires_mul * hires_mul * hires_mul);
+
+ for (i = 0; i < 3; i++) {
+ em->hmin[i] = em->min[i] * hires_mul;
+ em->hmax[i] = em->max[i] * hires_mul;
+ em->hres[i] = em->res[i] * hires_mul;
+ }
+
+ em->influence_high = MEM_calloc_arrayN(
+ total_cells_high, sizeof(float), "manta_flow_influence_high");
+ em->distances_high = MEM_malloc_arrayN(
+ total_cells_high, sizeof(float), "manta_flow_distances_high");
+ /* Initialize to infinity. */
+ memset(em->distances_high, 0x7f7f7f7f, sizeof(float) * total_cells_high);
+ }
+ em->valid = true;
+}
+
+static void em_freeData(EmissionMap *em)
+{
+ if (em->influence) {
+ MEM_freeN(em->influence);
+ }
+ if (em->influence_high) {
+ MEM_freeN(em->influence_high);
+ }
+ if (em->velocity) {
+ MEM_freeN(em->velocity);
+ }
+ if (em->distances) {
+ MEM_freeN(em->distances);
+ }
+ if (em->distances_high) {
+ MEM_freeN(em->distances_high);
+ }
+}
+
+static void em_combineMaps(
+ EmissionMap *output, EmissionMap *em2, int hires_multiplier, int additive, float sample_size)
+{
+ int i, x, y, z;
+
+ /* copyfill input 1 struct and clear output for new allocation */
+ EmissionMap em1;
+ memcpy(&em1, output, sizeof(EmissionMap));
+ memset(output, 0, sizeof(EmissionMap));
+
+ for (i = 0; i < 3; i++) {
+ if (em1.valid) {
+ output->min[i] = MIN2(em1.min[i], em2->min[i]);
+ output->max[i] = MAX2(em1.max[i], em2->max[i]);
+ }
+ else {
+ output->min[i] = em2->min[i];
+ output->max[i] = em2->max[i];
+ }
+ }
+ /* allocate output map */
+ em_allocateData(output, (em1.velocity || em2->velocity), hires_multiplier);
+
+ /* base resolution inputs */
+ for (x = output->min[0]; x < output->max[0]; x++) {
+ for (y = output->min[1]; y < output->max[1]; y++) {
+ for (z = output->min[2]; z < output->max[2]; z++) {
+ int index_out = manta_get_index(x - output->min[0],
+ output->res[0],
+ y - output->min[1],
+ output->res[1],
+ z - output->min[2]);
+
+ /* initialize with first input if in range */
+ if (x >= em1.min[0] && x < em1.max[0] && y >= em1.min[1] && y < em1.max[1] &&
+ z >= em1.min[2] && z < em1.max[2]) {
+ int index_in = manta_get_index(
+ x - em1.min[0], em1.res[0], y - em1.min[1], em1.res[1], z - em1.min[2]);
+
+ /* values */
+ output->influence[index_out] = em1.influence[index_in];
+ output->distances[index_out] = em1.distances[index_in];
+ if (output->velocity && em1.velocity) {
+ copy_v3_v3(&output->velocity[index_out * 3], &em1.velocity[index_in * 3]);
+ }
+ }
+
+ /* apply second input if in range */
+ if (x >= em2->min[0] && x < em2->max[0] && y >= em2->min[1] && y < em2->max[1] &&
+ z >= em2->min[2] && z < em2->max[2]) {
+ int index_in = manta_get_index(
+ x - em2->min[0], em2->res[0], y - em2->min[1], em2->res[1], z - em2->min[2]);
+
+ /* values */
+ if (additive) {
+ output->influence[index_out] += em2->influence[index_in] * sample_size;
+ }
+ else {
+ output->influence[index_out] = MAX2(em2->influence[index_in],
+ output->influence[index_out]);
+ }
+ output->distances[index_out] = MIN2(em2->distances[index_in],
+ output->distances[index_out]);
+ if (output->velocity && em2->velocity) {
+ /* last sample replaces the velocity */
+ output->velocity[index_out * 3] = ADD_IF_LOWER(output->velocity[index_out * 3],
+ em2->velocity[index_in * 3]);
+ output->velocity[index_out * 3 + 1] = ADD_IF_LOWER(output->velocity[index_out * 3 + 1],
+ em2->velocity[index_in * 3 + 1]);
+ output->velocity[index_out * 3 + 2] = ADD_IF_LOWER(output->velocity[index_out * 3 + 2],
+ em2->velocity[index_in * 3 + 2]);
+ }
+ }
+ } // low res loop
+ }
+ }
+
+ /* initialize high resolution input if available */
+ if (output->influence_high) {
+ for (x = output->hmin[0]; x < output->hmax[0]; x++) {
+ for (y = output->hmin[1]; y < output->hmax[1]; y++) {
+ for (z = output->hmin[2]; z < output->hmax[2]; z++) {
+ int index_out = manta_get_index(x - output->hmin[0],
+ output->hres[0],
+ y - output->hmin[1],
+ output->hres[1],
+ z - output->hmin[2]);
+
+ /* initialize with first input if in range */
+ if (x >= em1.hmin[0] && x < em1.hmax[0] && y >= em1.hmin[1] && y < em1.hmax[1] &&
+ z >= em1.hmin[2] && z < em1.hmax[2]) {
+ int index_in = manta_get_index(
+ x - em1.hmin[0], em1.hres[0], y - em1.hmin[1], em1.hres[1], z - em1.hmin[2]);
+ /* values */
+ output->influence_high[index_out] = em1.influence_high[index_in];
+ }
+
+ /* apply second input if in range */
+ if (x >= em2->hmin[0] && x < em2->hmax[0] && y >= em2->hmin[1] && y < em2->hmax[1] &&
+ z >= em2->hmin[2] && z < em2->hmax[2]) {
+ int index_in = manta_get_index(
+ x - em2->hmin[0], em2->hres[0], y - em2->hmin[1], em2->hres[1], z - em2->hmin[2]);
+
+ /* values */
+ if (additive) {
+ output->influence_high[index_out] += em2->distances_high[index_in] * sample_size;
+ }
+ else {
+ output->distances_high[index_out] = MAX2(em2->distances_high[index_in],
+ output->distances_high[index_out]);
+ }
+ output->distances_high[index_out] = MIN2(em2->distances_high[index_in],
+ output->distances_high[index_out]);
+ }
+ } // high res loop
+ }
+ }
+ }
+
+ /* free original data */
+ em_freeData(&em1);
+}
+
+typedef struct EmitFromParticlesData {
+ FluidFlowSettings *mfs;
+ KDTree_3d *tree;
+ int hires_multiplier;
+
+ EmissionMap *em;
+ float *particle_vel;
+ float hr;
+
+ int *min, *max, *res;
+
+ float solid;
+ float smooth;
+ float hr_smooth;
+} EmitFromParticlesData;
+
+static void emit_from_particles_task_cb(void *__restrict userdata,
+ const int z,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ EmitFromParticlesData *data = userdata;
+ FluidFlowSettings *mfs = data->mfs;
+ EmissionMap *em = data->em;
+ const int hires_multiplier = data->hires_multiplier;
+
+ for (int x = data->min[0]; x < data->max[0]; x++) {
+ for (int y = data->min[1]; y < data->max[1]; y++) {
+ /* Take low res samples where possible. */
+ if (hires_multiplier <= 1 ||
+ !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
+ /* Get low res space coordinates. */
+ float inv_multiplier = 1.0f / hires_multiplier;
+ const int lx = x * inv_multiplier;
+ const int ly = y * inv_multiplier;
+ const int lz = z * inv_multiplier;
+
+ const int index = manta_get_index(
+ lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
+ const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
+
+ /* Find particle distance from the kdtree. */
+ KDTreeNearest_3d nearest;
+ const float range = data->solid + data->smooth;
+ BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
+
+ if (nearest.dist < range) {
+ em->influence[index] = (nearest.dist < data->solid) ?
+ 1.0f :
+ (1.0f - (nearest.dist - data->solid) / data->smooth);
+ /* Uses particle velocity as initial velocity for smoke. */
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY &&
+ (mfs->psys->part->phystype != PART_PHYS_NO)) {
+ madd_v3_v3fl(
+ &em->velocity[index * 3], &data->particle_vel[nearest.index * 3], mfs->vel_multi);
+ }
+ }
+ }
+
+ /* Take high res samples if required. */
+ if (hires_multiplier > 1) {
+ /* get low res space coordinates */
+ const float lx = ((float)x) * data->hr;
+ const float ly = ((float)y) * data->hr;
+ const float lz = ((float)z) * data->hr;
+
+ const int index = manta_get_index(
+ x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
+ const float ray_start[3] = {
+ lx + 0.5f * data->hr, ly + 0.5f * data->hr, lz + 0.5f * data->hr};
+
+ /* Find particle distance from the kdtree. */
+ KDTreeNearest_3d nearest;
+ const float range = data->solid + data->hr_smooth;
+ BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
+
+ if (nearest.dist < range) {
+ em->influence_high[index] = (nearest.dist < data->solid) ?
+ 1.0f :
+ (1.0f - (nearest.dist - data->solid) / data->smooth);
+ }
+ }
+ }
+ }
+}
+
+static void emit_from_particles(Object *flow_ob,
+ FluidDomainSettings *mds,
+ FluidFlowSettings *mfs,
+ EmissionMap *em,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ float dt)
+{
+ if (mfs && mfs->psys && mfs->psys->part &&
+ ELEM(mfs->psys->part->type, PART_EMITTER, PART_FLUID)) // is particle system selected
+ {
+ ParticleSimulationData sim;
+ ParticleSystem *psys = mfs->psys;
+ float *particle_pos;
+ float *particle_vel;
+ int totpart = psys->totpart, totchild;
+ int p = 0;
+ int valid_particles = 0;
+ int bounds_margin = 1;
+
+ /* radius based flow */
+ const float solid = mfs->particle_size * 0.5f;
+ const float smooth = 0.5f; /* add 0.5 cells of linear falloff to reduce aliasing */
+ int hires_multiplier = 1;
+ KDTree_3d *tree = NULL;
+
+ sim.depsgraph = depsgraph;
+ sim.scene = scene;
+ sim.ob = flow_ob;
+ sim.psys = psys;
+ sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ /* prepare curvemapping tables */
+ if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve) {
+ BKE_curvemapping_changed_all(psys->part->clumpcurve);
+ }
+ if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) {
+ BKE_curvemapping_changed_all(psys->part->roughcurve);
+ }
+ if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve) {
+ BKE_curvemapping_changed_all(psys->part->twistcurve);
+ }
+
+ /* initialize particle cache */
+ if (psys->part->type == PART_HAIR) {
+ // TODO: PART_HAIR not supported whatsoever
+ totchild = 0;
+ }
+ else {
+ totchild = psys->totchild * psys->part->disp / 100;
+ }
+
+ particle_pos = MEM_callocN(sizeof(float) * (totpart + totchild) * 3,
+ "manta_flow_particles_pos");
+ particle_vel = MEM_callocN(sizeof(float) * (totpart + totchild) * 3,
+ "manta_flow_particles_vel");
+
+ /* setup particle radius emission if enabled */
+ if (mfs->flags & FLUID_FLOW_USE_PART_SIZE) {
+ tree = BLI_kdtree_3d_new(psys->totpart + psys->totchild);
+
+ /* check need for high resolution map */
+ if ((mds->flags & FLUID_DOMAIN_USE_NOISE) && (mds->highres_sampling == SM_HRES_FULLSAMPLE)) {
+ hires_multiplier = mds->noise_scale;
+ }
+
+ bounds_margin = (int)ceil(solid + smooth);
+ }
+
+ /* calculate local position for each particle */
+ for (p = 0; p < totpart + totchild; p++) {
+ ParticleKey state;
+ float *pos, *vel;
+ if (p < totpart) {
+ if (psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
+ continue;
+ }
+ }
+ else {
+ /* handle child particle */
+ ChildParticle *cpa = &psys->child[p - totpart];
+ if (psys->particles[cpa->parent].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
+ continue;
+ }
+ }
+
+ state.time = BKE_scene_frame_get(
+ scene); /* DEG_get_ctime(depsgraph) does not give subframe time */
+ if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
+ continue;
+ }
+
+ /* location */
+ pos = &particle_pos[valid_particles * 3];
+ copy_v3_v3(pos, state.co);
+ manta_pos_to_cell(mds, pos);
+
+ /* velocity */
+ vel = &particle_vel[valid_particles * 3];
+ copy_v3_v3(vel, state.vel);
+ mul_mat3_m4_v3(mds->imat, &particle_vel[valid_particles * 3]);
+
+ if (mfs->flags & FLUID_FLOW_USE_PART_SIZE) {
+ BLI_kdtree_3d_insert(tree, valid_particles, pos);
+ }
+
+ /* calculate emission map bounds */
+ em_boundInsert(em, pos);
+ valid_particles++;
+ }
+
+ /* set emission map */
+ clamp_bounds_in_domain(mds, em->min, em->max, NULL, NULL, bounds_margin, dt);
+ em_allocateData(em, mfs->flags & FLUID_FLOW_INITVELOCITY, hires_multiplier);
+
+ if (!(mfs->flags & FLUID_FLOW_USE_PART_SIZE)) {
+ for (p = 0; p < valid_particles; p++) {
+ int cell[3];
+ size_t i = 0;
+ size_t index = 0;
+ int badcell = 0;
+
+ /* 1. get corresponding cell */
+ cell[0] = floor(particle_pos[p * 3]) - em->min[0];
+ cell[1] = floor(particle_pos[p * 3 + 1]) - em->min[1];
+ cell[2] = floor(particle_pos[p * 3 + 2]) - em->min[2];
+ /* check if cell is valid (in the domain boundary) */
+ for (i = 0; i < 3; i++) {
+ if ((cell[i] > em->res[i] - 1) || (cell[i] < 0)) {
+ badcell = 1;
+ break;
+ }
+ }
+ if (badcell) {
+ continue;
+ }
+ /* get cell index */
+ index = manta_get_index(cell[0], em->res[0], cell[1], em->res[1], cell[2]);
+ /* Add influence to emission map */
+ em->influence[index] = 1.0f;
+ /* Uses particle velocity as initial velocity for smoke */
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO)) {
+ madd_v3_v3fl(&em->velocity[index * 3], &particle_vel[p * 3], mfs->vel_multi);
+ }
+ } // particles loop
+ }
+ else if (valid_particles > 0) { // FLUID_FLOW_USE_PART_SIZE
+ int min[3], max[3], res[3];
+ const float hr = 1.0f / ((float)hires_multiplier);
+ /* Slightly adjust high res anti-alias smoothness based on number of divisions
+ * to allow smaller details but yet not differing too much from the low res size. */
+ const float hr_smooth = smooth * powf(hr, 1.0f / 3.0f);
+
+ /* setup loop bounds */
+ for (int i = 0; i < 3; i++) {
+ min[i] = em->min[i] * hires_multiplier;
+ max[i] = em->max[i] * hires_multiplier;
+ res[i] = em->res[i] * hires_multiplier;
+ }
+
+ BLI_kdtree_3d_balance(tree);
+
+ EmitFromParticlesData data = {
+ .mfs = mfs,
+ .tree = tree,
+ .hires_multiplier = hires_multiplier,
+ .hr = hr,
+ .em = em,
+ .particle_vel = particle_vel,
+ .min = min,
+ .max = max,
+ .res = res,
+ .solid = solid,
+ .smooth = smooth,
+ .hr_smooth = hr_smooth,
+ };
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 2;
+ BLI_task_parallel_range(min[2], max[2], &data, emit_from_particles_task_cb, &settings);
+ }
+
+ if (mfs->flags & FLUID_FLOW_USE_PART_SIZE) {
+ BLI_kdtree_3d_free(tree);
+ }
+
+ /* free data */
+ if (particle_pos) {
+ MEM_freeN(particle_pos);
+ }
+ if (particle_vel) {
+ MEM_freeN(particle_vel);
+ }
+ }
+}
+
+/* Calculate map of (minimum) distances to flow/obstacle surface. Distances outside mesh are
+ * positive, inside negative. */
+static void update_mesh_distances(int index,
+ float *mesh_distances,
+ BVHTreeFromMesh *tree_data,
+ const float ray_start[3],
+ float surface_thickness,
+ int use_plane_init)
+{
+ float min_dist = FLT_MAX;
+
+ /* Ensure that planes get initialized correctly. */
+ if (use_plane_init) {
+ BVHTreeNearest nearest = {0};
+ nearest.index = -1;
+ nearest.dist_sq = surface_thickness;
+
+ if (BLI_bvhtree_find_nearest(
+ tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
+ float ray[3] = {0};
+ sub_v3_v3v3(ray, ray_start, nearest.co);
+ min_dist = len_v3(ray);
+ min_dist = (-1.0f) * fabsf(min_dist);
+ mesh_distances[index] = MIN2(mesh_distances[index], min_dist);
+ }
+ return;
+ }
+
+ /* First pass: Ray-casts in 26 directions
+ * (6 main axis + 12 quadrant diagonals (2D) + 8 octant diagonals (3D)). */
+ float ray_dirs[26][3] = {
+ {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f},
+ {0.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
+ {-1.0f, 1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, -1.0f},
+ {-1.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 1.0f}, {0.0f, 1.0f, -1.0f},
+ {0.0f, -1.0f, 1.0f}, {0.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {1.0f, -1.0f, -1.0f},
+ {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}};
+ size_t ray_cnt = sizeof ray_dirs / sizeof ray_dirs[0];
+
+ /* Count for ray misses (no face hit) and cases where ray direction matches face normal
+ * direction. */
+ int miss_cnt = 0, dir_cnt = 0;
+ min_dist = FLT_MAX;
+
+ for (int i = 0; i < ray_cnt; i++) {
+ BVHTreeRayHit hit_tree = {0};
+ hit_tree.index = -1;
+ hit_tree.dist = FLT_MAX;
+
+ normalize_v3(ray_dirs[i]);
+ BLI_bvhtree_ray_cast(tree_data->tree,
+ ray_start,
+ ray_dirs[i],
+ 0.0f,
+ &hit_tree,
+ tree_data->raycast_callback,
+ tree_data);
+
+ /* Ray did not hit mesh. Current point definitely not inside mesh. Inside mesh all rays have to
+ * hit. */
+ if (hit_tree.index == -1) {
+ miss_cnt++;
+ continue;
+ }
+
+ /* Ray and normal are in pointing opposite directions. */
+ if (dot_v3v3(ray_dirs[i], hit_tree.no) <= 0) {
+ dir_cnt++;
+ }
+
+ if (hit_tree.dist < min_dist) {
+ min_dist = hit_tree.dist;
+ }
+ }
+
+ /* Point lies inside mesh. Use negative sign for distance value. */
+ if (!(miss_cnt > 0 || dir_cnt == ray_cnt)) {
+ min_dist = (-1.0f) * fabsf(min_dist);
+ }
+
+ /* Update global distance array but ensure that older entries are not overridden. */
+ mesh_distances[index] = MIN2(mesh_distances[index], min_dist);
+
+ /* Second pass: Use nearest neighbor search on mesh surface. */
+ BVHTreeNearest nearest = {0};
+ nearest.index = -1;
+ nearest.dist_sq = 5;
+
+ if (BLI_bvhtree_find_nearest(
+ tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
+ float ray[3] = {0};
+ sub_v3_v3v3(ray, nearest.co, ray_start);
+ min_dist = len_v3(ray);
+ // CLAMP(min_dist, 0.5, min_dist);
+
+ BVHTreeRayHit hit_tree = {0};
+ hit_tree.index = -1;
+ hit_tree.dist = FLT_MAX;
+
+ normalize_v3(ray);
+ BLI_bvhtree_ray_cast(
+ tree_data->tree, ray_start, ray, 0.0f, &hit_tree, tree_data->raycast_callback, tree_data);
+
+ /* Only proceed if casted ray hit the mesh surface. */
+ if (hit_tree.index != -1) {
+
+ /* Ray and normal are in pointing same directions: Point must lie inside mesh. */
+ if (dot_v3v3(ray, hit_tree.no) > 0) {
+ min_dist = (-1.0f) * fabsf(min_dist);
+ }
+
+ /* Update distance value with more accurate one from this nearest neighbor search.
+ * Skip if new value would be outside and current value has inside value already. */
+ if (!(min_dist > 0 && mesh_distances[index] <= 0)) {
+ mesh_distances[index] = min_dist;
+ }
+ }
+ }
+
+ if (surface_thickness) {
+ mesh_distances[index] -= surface_thickness;
+ }
+}
+
+static void sample_mesh(FluidFlowSettings *mfs,
+ const MVert *mvert,
+ const MLoop *mloop,
+ const MLoopTri *mlooptri,
+ const MLoopUV *mloopuv,
+ float *influence_map,
+ float *velocity_map,
+ int index,
+ const int base_res[3],
+ float flow_center[3],
+ BVHTreeFromMesh *tree_data,
+ const float ray_start[3],
+ const float *vert_vel,
+ bool has_velocity,
+ int defgrp_index,
+ MDeformVert *dvert,
+ float x,
+ float y,
+ float z)
+{
+ float ray_dir[3] = {1.0f, 0.0f, 0.0f};
+ BVHTreeRayHit hit = {0};
+ BVHTreeNearest nearest = {0};
+
+ float volume_factor = 0.0f;
+ float sample_str = 0.0f;
+
+ hit.index = -1;
+ hit.dist = FLT_MAX;
+ nearest.index = -1;
+ nearest.dist_sq = mfs->surface_distance *
+ mfs->surface_distance; /* find_nearest uses squared distance */
+
+ /* Check volume collision */
+ if (mfs->volume_density) {
+ if (BLI_bvhtree_ray_cast(tree_data->tree,
+ ray_start,
+ ray_dir,
+ 0.0f,
+ &hit,
+ tree_data->raycast_callback,
+ tree_data) != -1) {
+ float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
+ /* If ray and hit face normal are facing same direction
+ * hit point is inside a closed mesh. */
+ if (dot >= 0) {
+ /* Also cast a ray in opposite direction to make sure
+ * point is at least surrounded by two faces */
+ negate_v3(ray_dir);
+ hit.index = -1;
+ hit.dist = FLT_MAX;
+
+ BLI_bvhtree_ray_cast(tree_data->tree,
+ ray_start,
+ ray_dir,
+ 0.0f,
+ &hit,
+ tree_data->raycast_callback,
+ tree_data);
+ if (hit.index != -1) {
+ volume_factor = mfs->volume_density;
+ }
+ }
+ }
+ }
+
+ /* find the nearest point on the mesh */
+ if (BLI_bvhtree_find_nearest(
+ tree_data->tree, ray_start, &nearest, tree_data->nearest_callback, tree_data) != -1) {
+ float weights[3];
+ int v1, v2, v3, f_index = nearest.index;
+ float n1[3], n2[3], n3[3], hit_normal[3];
+
+ /* emit from surface based on distance */
+ if (mfs->surface_distance) {
+ sample_str = sqrtf(nearest.dist_sq) / mfs->surface_distance;
+ CLAMP(sample_str, 0.0f, 1.0f);
+ sample_str = pow(1.0f - sample_str, 0.5f);
+ }
+ else {
+ sample_str = 0.0f;
+ }
+
+ /* calculate barycentric weights for nearest point */
+ v1 = mloop[mlooptri[f_index].tri[0]].v;
+ v2 = mloop[mlooptri[f_index].tri[1]].v;
+ v3 = mloop[mlooptri[f_index].tri[2]].v;
+ interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
+
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY && velocity_map) {
+ /* apply normal directional velocity */
+ if (mfs->vel_normal) {
+ /* interpolate vertex normal vectors to get nearest point normal */
+ normal_short_to_float_v3(n1, mvert[v1].no);
+ normal_short_to_float_v3(n2, mvert[v2].no);
+ normal_short_to_float_v3(n3, mvert[v3].no);
+ interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights);
+ normalize_v3(hit_normal);
+ /* apply normal directional and random velocity
+ * - TODO: random disabled for now since it doesn't really work well
+ * as pressure calc smoothens it out. */
+ velocity_map[index * 3] += hit_normal[0] * mfs->vel_normal * 0.25f;
+ velocity_map[index * 3 + 1] += hit_normal[1] * mfs->vel_normal * 0.25f;
+ velocity_map[index * 3 + 2] += hit_normal[2] * mfs->vel_normal * 0.25f;
+ /* TODO: for fire emitted from mesh surface we can use
+ * Vf = Vs + (Ps/Pf - 1)*S to model gaseous expansion from solid to fuel */
+ }
+ /* apply object velocity */
+ if (has_velocity && mfs->vel_multi) {
+ float hit_vel[3];
+ interp_v3_v3v3v3(
+ hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights);
+ velocity_map[index * 3] += hit_vel[0] * mfs->vel_multi;
+ velocity_map[index * 3 + 1] += hit_vel[1] * mfs->vel_multi;
+ velocity_map[index * 3 + 2] += hit_vel[2] * mfs->vel_multi;
+# ifdef DEBUG_PRINT
+ /* Debugging: Print flow object velocities. */
+ printf("adding flow object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]);
+# endif
+ }
+ velocity_map[index * 3] += mfs->vel_coord[0];
+ velocity_map[index * 3 + 1] += mfs->vel_coord[1];
+ velocity_map[index * 3 + 2] += mfs->vel_coord[2];
+ }
+
+ /* apply vertex group influence if used */
+ if (defgrp_index != -1 && dvert) {
+ float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
+ defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
+ defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
+ sample_str *= weight_mask;
+ }
+
+ /* apply emission texture */
+ if ((mfs->flags & FLUID_FLOW_TEXTUREEMIT) && mfs->noise_texture) {
+ float tex_co[3] = {0};
+ TexResult texres;
+
+ if (mfs->texture_type == FLUID_FLOW_TEXTURE_MAP_AUTO) {
+ tex_co[0] = ((x - flow_center[0]) / base_res[0]) / mfs->texture_size;
+ tex_co[1] = ((y - flow_center[1]) / base_res[1]) / mfs->texture_size;
+ tex_co[2] = ((z - flow_center[2]) / base_res[2] - mfs->texture_offset) / mfs->texture_size;
+ }
+ else if (mloopuv) {
+ const float *uv[3];
+ uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
+ uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
+ uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
+
+ interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
+
+ /* map between -1.0f and 1.0f */
+ tex_co[0] = tex_co[0] * 2.0f - 1.0f;
+ tex_co[1] = tex_co[1] * 2.0f - 1.0f;
+ tex_co[2] = mfs->texture_offset;
+ }
+ texres.nor = NULL;
+ BKE_texture_get_value(NULL, mfs->noise_texture, tex_co, &texres, false);
+ sample_str *= texres.tin;
+ }
+ }
+
+ /* multiply initial velocity by emitter influence */
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY && velocity_map) {
+ mul_v3_fl(&velocity_map[index * 3], sample_str);
+ }
+
+ /* apply final influence based on volume factor */
+ influence_map[index] = MAX2(volume_factor, sample_str);
+}
+
+typedef struct EmitFromDMData {
+ FluidDomainSettings *mds;
+ FluidFlowSettings *mfs;
+ const MVert *mvert;
+ const MLoop *mloop;
+ const MLoopTri *mlooptri;
+ const MLoopUV *mloopuv;
+ MDeformVert *dvert;
+ int defgrp_index;
+
+ BVHTreeFromMesh *tree;
+ int hires_multiplier;
+ float hr;
+
+ EmissionMap *em;
+ bool has_velocity;
+ float *vert_vel;
+
+ float *flow_center;
+ int *min, *max, *res;
+} EmitFromDMData;
+
+static void emit_from_mesh_task_cb(void *__restrict userdata,
+ const int z,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ EmitFromDMData *data = userdata;
+ EmissionMap *em = data->em;
+ const int hires_multiplier = data->hires_multiplier;
+
+ for (int x = data->min[0]; x < data->max[0]; x++) {
+ for (int y = data->min[1]; y < data->max[1]; y++) {
+ /* take low res samples where possible */
+ if (hires_multiplier <= 1 ||
+ !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
+ /* get low res space coordinates */
+ const int lx = x / hires_multiplier;
+ const int ly = y / hires_multiplier;
+ const int lz = z / hires_multiplier;
+
+ const int index = manta_get_index(
+ lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
+ const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
+
+ /* Emission for smoke and fire. Result in em->influence. Also, calculate invels */
+ sample_mesh(data->mfs,
+ data->mvert,
+ data->mloop,
+ data->mlooptri,
+ data->mloopuv,
+ em->influence,
+ em->velocity,
+ index,
+ data->mds->base_res,
+ data->flow_center,
+ data->tree,
+ ray_start,
+ data->vert_vel,
+ data->has_velocity,
+ data->defgrp_index,
+ data->dvert,
+ (float)lx,
+ (float)ly,
+ (float)lz);
+
+ /* Calculate levelset from meshes. Result in em->distances */
+ update_mesh_distances(index,
+ em->distances,
+ data->tree,
+ ray_start,
+ data->mfs->surface_distance,
+ data->mfs->flags & FLUID_FLOW_USE_PLANE_INIT);
+ }
+
+ /* take high res samples if required */
+ if (hires_multiplier > 1) {
+ /* get low res space coordinates */
+ const float lx = ((float)x) * data->hr;
+ const float ly = ((float)y) * data->hr;
+ const float lz = ((float)z) * data->hr;
+
+ const int index = manta_get_index(
+ x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
+ const float ray_start[3] = {
+ lx + 0.5f * data->hr,
+ ly + 0.5f * data->hr,
+ lz + 0.5f * data->hr,
+ };
+
+ /* Emission for smoke and fire high. Result in em->influence_high */
+ if (data->mfs->type == FLUID_FLOW_TYPE_SMOKE || data->mfs->type == FLUID_FLOW_TYPE_FIRE ||
+ data->mfs->type == FLUID_FLOW_TYPE_SMOKEFIRE) {
+ sample_mesh(data->mfs,
+ data->mvert,
+ data->mloop,
+ data->mlooptri,
+ data->mloopuv,
+ em->influence_high,
+ NULL,
+ index,
+ data->mds->base_res,
+ data->flow_center,
+ data->tree,
+ ray_start,
+ data->vert_vel,
+ data->has_velocity,
+ data->defgrp_index,
+ data->dvert,
+ /* x,y,z needs to be always lowres */
+ lx,
+ ly,
+ lz);
+ }
+ }
+ }
+ }
+}
+
+static void emit_from_mesh(
+ Object *flow_ob, FluidDomainSettings *mds, FluidFlowSettings *mfs, EmissionMap *em, float dt)
+{
+ if (mfs->mesh) {
+ Mesh *me = NULL;
+ MVert *mvert = NULL;
+ const MLoopTri *mlooptri = NULL;
+ const MLoop *mloop = NULL;
+ const MLoopUV *mloopuv = NULL;
+ MDeformVert *dvert = NULL;
+ BVHTreeFromMesh tree_data = {NULL};
+ int numverts, i;
+
+ float *vert_vel = NULL;
+ bool has_velocity = false;
+
+ int defgrp_index = mfs->vgroup_density - 1;
+ float flow_center[3] = {0};
+ int min[3], max[3], res[3];
+ int hires_multiplier = 1;
+
+ /* copy mesh for thread safety because we modify it,
+ * main issue is its VertArray being modified, then replaced and freed
+ */
+ me = BKE_mesh_copy_for_eval(mfs->mesh, true);
+
+ /* Duplicate vertices to modify. */
+ if (me->mvert) {
+ me->mvert = MEM_dupallocN(me->mvert);
+ CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
+ }
+
+ BKE_mesh_ensure_normals(me);
+ mvert = me->mvert;
+ mloop = me->mloop;
+ mlooptri = BKE_mesh_runtime_looptri_ensure(me);
+ numverts = me->totvert;
+ dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
+ mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, mfs->uvlayer_name);
+
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY) {
+ vert_vel = MEM_callocN(sizeof(float) * numverts * 3, "manta_flow_velocity");
+
+ if (mfs->numverts != numverts || !mfs->verts_old) {
+ if (mfs->verts_old) {
+ MEM_freeN(mfs->verts_old);
+ }
+ mfs->verts_old = MEM_callocN(sizeof(float) * numverts * 3, "manta_flow_verts_old");
+ mfs->numverts = numverts;
+ }
+ else {
+ has_velocity = true;
+ }
+ }
+
+ /* Transform mesh vertices to
+ * domain grid space for fast lookups */
+ for (i = 0; i < numverts; i++) {
+ float n[3];
+
+ /* vert pos */
+ mul_m4_v3(flow_ob->obmat, mvert[i].co);
+ manta_pos_to_cell(mds, mvert[i].co);
+
+ /* vert normal */
+ normal_short_to_float_v3(n, mvert[i].no);
+ mul_mat3_m4_v3(flow_ob->obmat, n);
+ mul_mat3_m4_v3(mds->imat, n);
+ normalize_v3(n);
+ normal_float_to_short_v3(mvert[i].no, n);
+
+ /* vert velocity */
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY) {
+ float co[3];
+ add_v3fl_v3fl_v3i(co, mvert[i].co, mds->shift);
+ if (has_velocity) {
+ sub_v3_v3v3(&vert_vel[i * 3], co, &mfs->verts_old[i * 3]);
+ mul_v3_fl(&vert_vel[i * 3], mds->dx / dt);
+ }
+ copy_v3_v3(&mfs->verts_old[i * 3], co);
+ }
+
+ /* calculate emission map bounds */
+ em_boundInsert(em, mvert[i].co);
+ }
+ mul_m4_v3(flow_ob->obmat, flow_center);
+ manta_pos_to_cell(mds, flow_center);
+
+ /* check need for high resolution map */
+ if ((mds->flags & FLUID_DOMAIN_USE_NOISE) && (mds->highres_sampling == SM_HRES_FULLSAMPLE)) {
+ hires_multiplier = mds->noise_scale;
+ }
+
+ /* set emission map */
+ clamp_bounds_in_domain(
+ mds, em->min, em->max, NULL, NULL, (int)ceil(mfs->surface_distance), dt);
+ em_allocateData(em, mfs->flags & FLUID_FLOW_INITVELOCITY, hires_multiplier);
+
+ /* setup loop bounds */
+ for (i = 0; i < 3; i++) {
+ min[i] = em->min[i] * hires_multiplier;
+ max[i] = em->max[i] * hires_multiplier;
+ res[i] = em->res[i] * hires_multiplier;
+ }
+
+ if (BKE_bvhtree_from_mesh_get(&tree_data, me, BVHTREE_FROM_LOOPTRI, 4)) {
+ const float hr = 1.0f / ((float)hires_multiplier);
+
+ EmitFromDMData data = {
+ .mds = mds,
+ .mfs = mfs,
+ .mvert = mvert,
+ .mloop = mloop,
+ .mlooptri = mlooptri,
+ .mloopuv = mloopuv,
+ .dvert = dvert,
+ .defgrp_index = defgrp_index,
+ .tree = &tree_data,
+ .hires_multiplier = hires_multiplier,
+ .hr = hr,
+ .em = em,
+ .has_velocity = has_velocity,
+ .vert_vel = vert_vel,
+ .flow_center = flow_center,
+ .min = min,
+ .max = max,
+ .res = res,
+ };
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 2;
+ BLI_task_parallel_range(min[2], max[2], &data, emit_from_mesh_task_cb, &settings);
+ }
+ /* free bvh tree */
+ free_bvhtree_from_mesh(&tree_data);
+
+ if (vert_vel) {
+ MEM_freeN(vert_vel);
+ }
+ if (me->mvert) {
+ MEM_freeN(me->mvert);
+ }
+ BKE_id_free(NULL, me);
+ }
+}
+
+/**********************************************************
+ * Smoke step
+ **********************************************************/
+
+static void adaptive_domain_adjust(
+ FluidDomainSettings *mds, Object *ob, EmissionMap *emaps, uint numflowobj, float dt)
+{
+ /* calculate domain shift for current frame */
+ int new_shift[3] = {0};
+ int total_shift[3];
+ float frame_shift_f[3];
+ float ob_loc[3] = {0};
+
+ mul_m4_v3(ob->obmat, ob_loc);
+
+ sub_v3_v3v3(frame_shift_f, ob_loc, mds->prev_loc);
+ copy_v3_v3(mds->prev_loc, ob_loc);
+ /* convert global space shift to local "cell" space */
+ mul_mat3_m4_v3(mds->imat, frame_shift_f);
+ frame_shift_f[0] = frame_shift_f[0] / mds->cell_size[0];
+ frame_shift_f[1] = frame_shift_f[1] / mds->cell_size[1];
+ frame_shift_f[2] = frame_shift_f[2] / mds->cell_size[2];
+ /* add to total shift */
+ add_v3_v3(mds->shift_f, frame_shift_f);
+ /* convert to integer */
+ total_shift[0] = (int)(floorf(mds->shift_f[0]));
+ total_shift[1] = (int)(floorf(mds->shift_f[1]));
+ total_shift[2] = (int)(floorf(mds->shift_f[2]));
+ int temp_shift[3];
+ copy_v3_v3_int(temp_shift, mds->shift);
+ sub_v3_v3v3_int(new_shift, total_shift, mds->shift);
+ copy_v3_v3_int(mds->shift, total_shift);
+
+ /* calculate new domain boundary points so that smoke doesn't slide on sub-cell movement */
+ mds->p0[0] = mds->dp0[0] - mds->cell_size[0] * (mds->shift_f[0] - total_shift[0] - 0.5f);
+ mds->p0[1] = mds->dp0[1] - mds->cell_size[1] * (mds->shift_f[1] - total_shift[1] - 0.5f);
+ mds->p0[2] = mds->dp0[2] - mds->cell_size[2] * (mds->shift_f[2] - total_shift[2] - 0.5f);
+ mds->p1[0] = mds->p0[0] + mds->cell_size[0] * mds->base_res[0];
+ mds->p1[1] = mds->p0[1] + mds->cell_size[1] * mds->base_res[1];
+ mds->p1[2] = mds->p0[2] + mds->cell_size[2] * mds->base_res[2];
+
+ /* adjust domain resolution */
+ const int block_size = mds->noise_scale;
+ 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];
+ int x, y, z;
+ float *density = manta_smoke_get_density(mds->fluid);
+ float *fuel = manta_smoke_get_fuel(mds->fluid);
+ float *bigdensity = manta_smoke_turbulence_get_density(mds->fluid);
+ float *bigfuel = manta_smoke_turbulence_get_fuel(mds->fluid);
+ float *vx = manta_get_velocity_x(mds->fluid);
+ float *vy = manta_get_velocity_y(mds->fluid);
+ float *vz = manta_get_velocity_z(mds->fluid);
+ int wt_res[3];
+
+ if (mds->flags & FLUID_DOMAIN_USE_NOISE && mds->fluid) {
+ manta_smoke_turbulence_get_res(mds->fluid, wt_res);
+ }
+
+ INIT_MINMAX(min_vel, max_vel);
+
+ /* Calculate bounds for current domain content */
+ for (x = mds->res_min[0]; x < mds->res_max[0]; x++) {
+ for (y = mds->res_min[1]; y < mds->res_max[1]; y++) {
+ for (z = mds->res_min[2]; z < mds->res_max[2]; z++) {
+ int xn = x - new_shift[0];
+ int yn = y - new_shift[1];
+ int zn = z - new_shift[2];
+ int index;
+ float max_den;
+
+ /* skip if cell already belongs to new area */
+ if (xn >= min[0] && xn <= max[0] && yn >= min[1] && yn <= max[1] && zn >= min[2] &&
+ zn <= max[2]) {
+ continue;
+ }
+
+ index = manta_get_index(x - mds->res_min[0],
+ mds->res[0],
+ y - mds->res_min[1],
+ mds->res[1],
+ z - mds->res_min[2]);
+ max_den = (fuel) ? MAX2(density[index], fuel[index]) : density[index];
+
+ /* check high resolution bounds if max density isnt already high enough */
+ if (max_den < mds->adapt_threshold && mds->flags & FLUID_DOMAIN_USE_NOISE && mds->fluid) {
+ int i, j, k;
+ /* high res grid index */
+ int xx = (x - mds->res_min[0]) * block_size;
+ int yy = (y - mds->res_min[1]) * block_size;
+ int zz = (z - mds->res_min[2]) * block_size;
+
+ for (i = 0; i < block_size; i++) {
+ for (j = 0; j < block_size; j++) {
+ for (k = 0; k < block_size; k++) {
+ int big_index = manta_get_index(xx + i, wt_res[0], yy + j, wt_res[1], zz + k);
+ float den = (bigfuel) ? MAX2(bigdensity[big_index], bigfuel[big_index]) :
+ bigdensity[big_index];
+ if (den > max_den) {
+ max_den = den;
+ }
+ }
+ }
+ }
+ }
+
+ /* content bounds (use shifted coordinates) */
+ if (max_den >= mds->adapt_threshold) {
+ if (min[0] > xn) {
+ min[0] = xn;
+ }
+ if (min[1] > yn) {
+ min[1] = yn;
+ }
+ if (min[2] > zn) {
+ min[2] = zn;
+ }
+ if (max[0] < xn) {
+ max[0] = xn;
+ }
+ if (max[1] < yn) {
+ max[1] = yn;
+ }
+ if (max[2] < zn) {
+ max[2] = zn;
+ }
+ }
+
+ /* velocity bounds */
+ if (min_vel[0] > vx[index]) {
+ min_vel[0] = vx[index];
+ }
+ if (min_vel[1] > vy[index]) {
+ min_vel[1] = vy[index];
+ }
+ if (min_vel[2] > vz[index]) {
+ min_vel[2] = vz[index];
+ }
+ if (max_vel[0] < vx[index]) {
+ max_vel[0] = vx[index];
+ }
+ if (max_vel[1] < vy[index]) {
+ max_vel[1] = vy[index];
+ }
+ if (max_vel[2] < vz[index]) {
+ max_vel[2] = vz[index];
+ }
+ }
+ }
+ }
+
+ /* also apply emission maps */
+ for (int i = 0; i < numflowobj; i++) {
+ EmissionMap *em = &emaps[i];
+
+ for (x = em->min[0]; x < em->max[0]; x++) {
+ for (y = em->min[1]; y < em->max[1]; y++) {
+ for (z = em->min[2]; z < em->max[2]; z++) {
+ int index = manta_get_index(
+ x - em->min[0], em->res[0], y - em->min[1], em->res[1], z - em->min[2]);
+ float max_den = em->influence[index];
+
+ /* density bounds */
+ if (max_den >= mds->adapt_threshold) {
+ if (min[0] > x) {
+ min[0] = x;
+ }
+ if (min[1] > y) {
+ min[1] = y;
+ }
+ if (min[2] > z) {
+ min[2] = z;
+ }
+ if (max[0] < x) {
+ max[0] = x;
+ }
+ if (max[1] < y) {
+ max[1] = y;
+ }
+ if (max[2] < z) {
+ max[2] = z;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* calculate new bounds based on these values */
+ clamp_bounds_in_domain(mds, min, max, min_vel, max_vel, mds->adapt_margin + 1, dt);
+
+ for (int i = 0; i < 3; i++) {
+ /* calculate new resolution */
+ res[i] = max[i] - min[i];
+ total_cells *= res[i];
+
+ if (new_shift[i]) {
+ shift_changed = 1;
+ }
+
+ /* if no content set minimum dimensions */
+ if (res[i] <= 0) {
+ int j;
+ for (j = 0; j < 3; j++) {
+ min[j] = 0;
+ max[j] = 1;
+ res[j] = 1;
+ }
+ res_changed = 1;
+ total_cells = 1;
+ break;
+ }
+ if (min[i] != mds->res_min[i] || max[i] != mds->res_max[i]) {
+ res_changed = 1;
+ }
+ }
+
+ if (res_changed || shift_changed) {
+ BKE_fluid_reallocate_copy_fluid(
+ mds, mds->res, res, mds->res_min, min, mds->res_max, temp_shift, total_shift);
+
+ /* set new domain dimensions */
+ copy_v3_v3_int(mds->res_min, min);
+ copy_v3_v3_int(mds->res_max, max);
+ copy_v3_v3_int(mds->res, res);
+ mds->total_cells = total_cells;
+
+ /* Redo adapt time step in manta to refresh solver state (ie time variables) */
+ manta_adapt_timestep(mds->fluid);
+ }
+
+ /* update global size field with new bbox size */
+ /* volume bounds */
+ float minf[3], maxf[3], size[3];
+ madd_v3fl_v3fl_v3fl_v3i(minf, mds->p0, mds->cell_size, mds->res_min);
+ madd_v3fl_v3fl_v3fl_v3i(maxf, mds->p0, mds->cell_size, mds->res_max);
+ /* calculate domain dimensions */
+ sub_v3_v3v3(size, maxf, minf);
+ /* apply object scale */
+ for (int i = 0; i < 3; i++) {
+ size[i] = fabsf(size[i] * ob->scale[i]);
+ }
+ copy_v3_v3(mds->global_size, size);
+}
+
+BLI_INLINE void apply_outflow_fields(int index,
+ float distance_value,
+ float *density,
+ float *heat,
+ float *fuel,
+ float *react,
+ float *color_r,
+ float *color_g,
+ float *color_b,
+ float *phiout)
+{
+ /* determine outflow cells - phiout used in smoke and liquids */
+ if (phiout) {
+ phiout[index] = distance_value;
+ }
+
+ /* set smoke outflow */
+ if (density) {
+ density[index] = 0.0f;
+ }
+ if (heat) {
+ heat[index] = 0.0f;
+ }
+ if (fuel) {
+ fuel[index] = 0.0f;
+ react[index] = 0.0f;
+ }
+ if (color_r) {
+ color_r[index] = 0.0f;
+ color_g[index] = 0.0f;
+ color_b[index] = 0.0f;
+ }
+}
+
+BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
+ float emission_value,
+ float distance_value,
+ int index,
+ float *density_in,
+ const float *density,
+ float *heat_in,
+ const float *heat,
+ float *fuel_in,
+ const float *fuel,
+ float *react_in,
+ const float *react,
+ float *color_r_in,
+ const float *color_r,
+ float *color_g_in,
+ const float *color_g,
+ float *color_b_in,
+ const float *color_b,
+ float *phi_in,
+ float *emission_in)
+{
+ /* add inflow */
+ if (phi_in) {
+ phi_in[index] = distance_value;
+ }
+
+ /* save emission value for manta inflow */
+ if (emission_in) {
+ emission_in[index] = emission_value;
+ }
+
+ /* add smoke inflow */
+ int absolute_flow = (mfs->flags & FLUID_FLOW_ABSOLUTE);
+ float dens_old = (density) ? density[index] : 0.0;
+ // float fuel_old = (fuel) ? fuel[index] : 0.0f; /* UNUSED */
+ float dens_flow = (mfs->type == FLUID_FLOW_TYPE_FIRE) ? 0.0f : emission_value * mfs->density;
+ float fuel_flow = (fuel) ? emission_value * mfs->fuel_amount : 0.0f;
+ /* add heat */
+ if (heat && heat_in) {
+ if (emission_value > 0.0f) {
+ heat_in[index] = ADD_IF_LOWER(heat[index], mfs->temperature);
+ /* Scale inflow by dt/frame-length.
+ * This is to ensure that adaptive steps don't apply too much emission. */
+ }
+ else {
+ heat_in[index] = heat[index];
+ }
+ }
+
+ /* set density and fuel - absolute mode */
+ if (absolute_flow) {
+ if (density && density_in) {
+ density_in[index] = density[index];
+ if (mfs->type != FLUID_FLOW_TYPE_FIRE && dens_flow > density[index]) {
+ density_in[index] = dens_flow;
+ }
+ }
+ if (fuel && fuel_in) {
+ fuel_in[index] = fuel[index];
+ if (mfs->type != FLUID_FLOW_TYPE_SMOKE && fuel_flow && fuel_flow > fuel[index]) {
+ fuel_in[index] = fuel_flow;
+ }
+ }
+ }
+ /* set density and fuel - additive mode */
+ else {
+ if (density && density_in) {
+ density_in[index] = density[index];
+ if (mfs->type != FLUID_FLOW_TYPE_FIRE) {
+ density_in[index] += dens_flow;
+ CLAMP(density_in[index], 0.0f, 1.0f);
+ }
+ }
+ if (fuel && fuel_in) {
+ fuel_in[index] = fuel[index];
+ if (mfs->type != FLUID_FLOW_TYPE_SMOKE && mfs->fuel_amount) {
+ fuel_in[index] += fuel_flow;
+ CLAMP(fuel_in[index], 0.0f, 10.0f);
+ }
+ }
+ }
+
+ /* set color */
+ if (color_r && color_r_in) {
+ color_r_in[index] = color_r[index];
+ color_g_in[index] = color_g[index];
+ color_b_in[index] = color_b[index];
+
+ if (dens_flow) {
+ float total_dens = density[index] / (dens_old + dens_flow);
+ color_r_in[index] = (color_r[index] + mfs->color[0] * dens_flow) * total_dens;
+ color_g_in[index] = (color_g[index] + mfs->color[1] * dens_flow) * total_dens;
+ color_b_in[index] = (color_b[index] + mfs->color[2] * dens_flow) * total_dens;
+ }
+ }
+
+ /* set fire reaction coordinate */
+ if (fuel && fuel_in) {
+ /* Instead of using 1.0 for all new fuel add slight falloff to reduce flow blocky-ness. */
+ float value = 1.0f - pow2f(1.0f - emission_value);
+
+ if (fuel[index] > FLT_EPSILON && value > react[index]) {
+ float f = fuel_flow / fuel[index];
+ react_in[index] = value * f + (1.0f - f) * react[index];
+ CLAMP(react_in[index], 0.0f, value);
+ }
+ else {
+ react_in[index] = react[index];
+ }
+ }
+}
+
+static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int numflowobj)
+{
+ int active_fields = mds->active_fields;
+ uint flow_index;
+
+ /* Monitor active fields based on flow settings */
+ for (flow_index = 0; flow_index < numflowobj; flow_index++) {
+ Object *coll_ob = flowobjs[flow_index];
+ FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(coll_ob,
+ eModifierType_Fluid);
+
+ // Sanity check
+ if (!mmd2) {
+ continue;
+ }
+
+ /* First, remove all flags that we want to update. */
+ int prev_flags = (FLUID_DOMAIN_ACTIVE_INVEL | FLUID_DOMAIN_ACTIVE_OUTFLOW |
+ FLUID_DOMAIN_ACTIVE_HEAT | FLUID_DOMAIN_ACTIVE_FIRE |
+ FLUID_DOMAIN_ACTIVE_COLOR_SET | FLUID_DOMAIN_ACTIVE_COLORS);
+ active_fields &= ~prev_flags;
+
+ if ((mmd2->type & MOD_FLUID_TYPE_FLOW) && mmd2->flow) {
+ FluidFlowSettings *mfs = mmd2->flow;
+ if (!mfs) {
+ break;
+ }
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY) {
+ active_fields |= FLUID_DOMAIN_ACTIVE_INVEL;
+ }
+ if (mfs->behavior == FLUID_FLOW_BEHAVIOR_OUTFLOW) {
+ active_fields |= FLUID_DOMAIN_ACTIVE_OUTFLOW;
+ }
+ /* liquids done from here */
+ if (mds->type == FLUID_DOMAIN_TYPE_LIQUID) {
+ continue;
+ }
+
+ /* activate heat field if flow produces any heat */
+ if (mfs->temperature) {
+ active_fields |= FLUID_DOMAIN_ACTIVE_HEAT;
+ }
+ /* activate fuel field if flow adds any fuel */
+ if (mfs->fuel_amount &&
+ (mfs->type == FLUID_FLOW_TYPE_FIRE || mfs->type == FLUID_FLOW_TYPE_SMOKEFIRE)) {
+ active_fields |= FLUID_DOMAIN_ACTIVE_FIRE;
+ }
+ /* activate color field if flows add smoke with varying colors */
+ if (mfs->density &&
+ (mfs->type == FLUID_FLOW_TYPE_SMOKE || mfs->type == FLUID_FLOW_TYPE_SMOKEFIRE)) {
+ if (!(active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET)) {
+ copy_v3_v3(mds->active_color, mfs->color);
+ active_fields |= FLUID_DOMAIN_ACTIVE_COLOR_SET;
+ }
+ else if (!equals_v3v3(mds->active_color, mfs->color)) {
+ copy_v3_v3(mds->active_color, mfs->color);
+ active_fields |= FLUID_DOMAIN_ACTIVE_COLORS;
+ }
+ }
+ }
+ }
+ /* Monitor active fields based on domain settings */
+ if (mds->type == FLUID_DOMAIN_TYPE_GAS && active_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
+ /* heat is always needed for fire */
+ active_fields |= FLUID_DOMAIN_ACTIVE_HEAT;
+ /* also activate colors if domain smoke color differs from active color */
+ if (!(active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET)) {
+ copy_v3_v3(mds->active_color, mds->flame_smoke_color);
+ active_fields |= FLUID_DOMAIN_ACTIVE_COLOR_SET;
+ }
+ else if (!equals_v3v3(mds->active_color, mds->flame_smoke_color)) {
+ copy_v3_v3(mds->active_color, mds->flame_smoke_color);
+ active_fields |= FLUID_DOMAIN_ACTIVE_COLORS;
+ }
+ }
+ /* Finally, initialize new data fields if any */
+ if (active_fields & FLUID_DOMAIN_ACTIVE_INVEL) {
+ manta_ensure_invelocity(mds->fluid, mds->mmd);
+ }
+ if (active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW) {
+ manta_ensure_outflow(mds->fluid, mds->mmd);
+ }
+ if (active_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
+ manta_smoke_ensure_heat(mds->fluid, mds->mmd);
+ }
+ if (active_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
+ manta_smoke_ensure_fire(mds->fluid, mds->mmd);
+ }
+ if (active_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
+ /* initialize all smoke with "active_color" */
+ manta_smoke_ensure_colors(mds->fluid, mds->mmd);
+ }
+ if (mds->type == FLUID_DOMAIN_TYPE_LIQUID &&
+ (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY ||
+ mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM ||
+ mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)) {
+ manta_liquid_ensure_sndparts(mds->fluid, mds->mmd);
+ }
+ mds->active_fields = active_fields;
+}
+
+static void update_flowsfluids(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ FluidDomainSettings *mds,
+ float time_per_frame,
+ float frame_length,
+ int frame,
+ float dt)
+{
+ EmissionMap *emaps = NULL;
+ Object **flowobjs = NULL;
+ uint numflowobj = 0, flow_index = 0;
+ bool is_first_frame = (frame == mds->cache_frame_start);
+
+ flowobjs = BKE_collision_objects_create(
+ depsgraph, ob, mds->fluid_group, &numflowobj, eModifierType_Fluid);
+
+ /* Update all flow related flags and ensure that corresponding grids get initialized */
+ update_flowsflags(mds, flowobjs, numflowobj);
+
+ /* init emission maps for each flow */
+ emaps = MEM_callocN(sizeof(struct EmissionMap) * numflowobj, "manta_flow_maps");
+
+ /* Prepare flow emission maps */
+ for (flow_index = 0; flow_index < numflowobj; flow_index++) {
+ Object *flowobj = flowobjs[flow_index];
+ FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj,
+ eModifierType_Fluid);
+
+ /* Check for initialized smoke object */
+ if ((mmd2->type & MOD_FLUID_TYPE_FLOW) && mmd2->flow) {
+ FluidFlowSettings *mfs = mmd2->flow;
+ int subframes = mfs->subframes;
+ EmissionMap *em = &emaps[flow_index];
+
+ /* Length of one adaptive frame. If using adaptive stepping, length is smaller than actual
+ * frame length */
+ float adaptframe_length = time_per_frame / frame_length;
+ /* Adaptive frame length as percentage */
+ CLAMP(adaptframe_length, 0.0f, 1.0f);
+
+ /* Further splitting because of emission subframe: If no subframes present, sample_size is 1
+ */
+ float sample_size = 1.0f / (float)(subframes + 1);
+ int hires_multiplier = 1;
+
+ /* First frame cannot have any subframes because there is (obviously) no previous frame from
+ * where subframes could come from */
+ if (is_first_frame) {
+ subframes = 0;
+ }
+
+ int subframe;
+ float subframe_dt = dt * sample_size;
+
+ /* Emission loop. When not using subframes this will loop only once. */
+ for (subframe = subframes; subframe >= 0; subframe--) {
+
+ /* Temporary emission map used when subframes are enabled, i.e. at least one subframe */
+ EmissionMap em_temp = {NULL};
+
+ /* Set scene time */
+ /* Handle emission subframe */
+ if (subframe > 0 && !is_first_frame) {
+ scene->r.subframe = adaptframe_length -
+ sample_size * (float)(subframe) * (dt / frame_length);
+ scene->r.cfra = frame - 1;
+ }
+ /* Last frame in this loop (subframe == suframes). Can be real end frame or in between
+ * frames (adaptive frame) */
+ else {
+ /* Handle adaptive subframe (ie has subframe fraction). Need to set according scene
+ * subframe parameter */
+ if (time_per_frame < frame_length) {
+ scene->r.subframe = adaptframe_length;
+ scene->r.cfra = frame - 1;
+ }
+ /* Handle absolute endframe (ie no subframe fraction). Need to set the scene subframe
+ * parameter to 0 and advance current scene frame */
+ else {
+ scene->r.subframe = 0.0f;
+ scene->r.cfra = frame;
+ }
+ }
+ /* Sanity check: subframe portion must be between 0 and 1 */
+ CLAMP(scene->r.subframe, 0.0f, 1.0f);
+# ifdef DEBUG_PRINT
+ /* Debugging: Print subframe information. */
+ printf(
+ "flow: frame (is first: %d): %d // scene current frame: %d // scene current subframe: "
+ "%f\n",
+ is_first_frame,
+ frame,
+ scene->r.cfra,
+ scene->r.subframe);
+# endif
+ /* Update frame time, this is considering current subframe fraction
+ * BLI_mutex_lock() called in manta_step(), so safe to update subframe here
+ * TODO (sebbas): Using BKE_scene_frame_get(scene) instead of new DEG_get_ctime(depsgraph)
+ * as subframes don't work with the latter yet */
+ BKE_object_modifier_update_subframe(
+ depsgraph, scene, flowobj, true, 5, BKE_scene_frame_get(scene), eModifierType_Fluid);
+
+ /* Emission from particles */
+ if (mfs->source == FLUID_FLOW_SOURCE_PARTICLES) {
+ if (subframes) {
+ emit_from_particles(flowobj, mds, mfs, &em_temp, depsgraph, scene, subframe_dt);
+ }
+ else {
+ emit_from_particles(flowobj, mds, mfs, em, depsgraph, scene, subframe_dt);
+ }
+
+ if (!(mfs->flags & FLUID_FLOW_USE_PART_SIZE)) {
+ hires_multiplier = 1;
+ }
+ }
+ /* Emission from mesh */
+ else if (mfs->source == FLUID_FLOW_SOURCE_MESH) {
+ if (subframes) {
+ emit_from_mesh(flowobj, mds, mfs, &em_temp, subframe_dt);
+ }
+ else {
+ emit_from_mesh(flowobj, mds, mfs, em, subframe_dt);
+ }
+ }
+ else {
+ printf("Error: unknown flow emission source\n");
+ }
+
+ /* If this we emitted with temp emission map in this loop (subframe emission), we combine
+ * the temp map with the original emission map */
+ if (subframes) {
+ /* Combine emission maps */
+ em_combineMaps(
+ em, &em_temp, hires_multiplier, !(mfs->flags & FLUID_FLOW_ABSOLUTE), sample_size);
+ em_freeData(&em_temp);
+ }
+ }
+ }
+ }
+# ifdef DEBUG_PRINT
+ /* Debugging: Print time information. */
+ printf("flow: frame: %d // time per frame: %f // frame length: %f // dt: %f\n",
+ frame,
+ time_per_frame,
+ frame_length,
+ dt);
+# endif
+
+ /* Adjust domain size if needed. Only do this once for every frame */
+ if (mds->type == FLUID_DOMAIN_TYPE_GAS && mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
+ adaptive_domain_adjust(mds, ob, emaps, numflowobj, dt);
+ }
+
+ float *phi_in = manta_get_phi_in(mds->fluid);
+ float *phiout_in = manta_get_phiout_in(mds->fluid);
+ float *density = manta_smoke_get_density(mds->fluid);
+ float *color_r = manta_smoke_get_color_r(mds->fluid);
+ float *color_g = manta_smoke_get_color_g(mds->fluid);
+ float *color_b = manta_smoke_get_color_b(mds->fluid);
+ float *fuel = manta_smoke_get_fuel(mds->fluid);
+ float *heat = manta_smoke_get_heat(mds->fluid);
+ float *react = manta_smoke_get_react(mds->fluid);
+
+ float *density_in = manta_smoke_get_density_in(mds->fluid);
+ float *heat_in = manta_smoke_get_heat_in(mds->fluid);
+ float *color_r_in = manta_smoke_get_color_r_in(mds->fluid);
+ float *color_g_in = manta_smoke_get_color_g_in(mds->fluid);
+ float *color_b_in = manta_smoke_get_color_b_in(mds->fluid);
+ float *fuel_in = manta_smoke_get_fuel_in(mds->fluid);
+ float *react_in = manta_smoke_get_react_in(mds->fluid);
+ float *emission_in = manta_smoke_get_emission_in(mds->fluid);
+
+ float *velx_initial = manta_get_in_velocity_x(mds->fluid);
+ float *vely_initial = manta_get_in_velocity_y(mds->fluid);
+ float *velz_initial = manta_get_in_velocity_z(mds->fluid);
+ uint z;
+
+ /* Grid reset before writing again */
+ for (z = 0; z < mds->res[0] * mds->res[1] * mds->res[2]; z++) {
+ if (phi_in) {
+ phi_in[z] = FLT_MAX;
+ }
+ if (phiout_in) {
+ phiout_in[z] = FLT_MAX;
+ }
+ if (density_in) {
+ density_in[z] = 0.0f;
+ }
+ if (heat_in) {
+ heat_in[z] = 0.0f;
+ }
+ if (color_r_in) {
+ color_r_in[z] = 0.0f;
+ color_g_in[z] = 0.0f;
+ color_b_in[z] = 0.0f;
+ }
+ if (fuel_in) {
+ fuel_in[z] = 0.0f;
+ react_in[z] = 0.0f;
+ }
+ if (emission_in) {
+ emission_in[z] = 0.0f;
+ }
+ if (velx_initial) {
+ velx_initial[z] = 0.0f;
+ vely_initial[z] = 0.0f;
+ velz_initial[z] = 0.0f;
+ }
+ }
+
+ /* Apply emission data */
+ for (flow_index = 0; flow_index < numflowobj; flow_index++) {
+ Object *flowobj = flowobjs[flow_index];
+ FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj,
+ eModifierType_Fluid);
+
+ // check for initialized flow object
+ if ((mmd2->type & MOD_FLUID_TYPE_FLOW) && mmd2->flow) {
+ FluidFlowSettings *mfs = mmd2->flow;
+ EmissionMap *em = &emaps[flow_index];
+ float *velocity_map = em->velocity;
+ float *emission_map = em->influence;
+ float *distance_map = em->distances;
+
+ int gx, gy, gz, ex, ey, ez, dx, dy, dz;
+ size_t e_index, d_index;
+
+ // loop through every emission map cell
+ for (gx = em->min[0]; gx < em->max[0]; gx++) {
+ for (gy = em->min[1]; gy < em->max[1]; gy++) {
+ for (gz = em->min[2]; gz < em->max[2]; gz++) {
+ /* get emission map index */
+ ex = gx - em->min[0];
+ ey = gy - em->min[1];
+ ez = gz - em->min[2];
+ e_index = manta_get_index(ex, em->res[0], ey, em->res[1], ez);
+
+ /* get domain index */
+ dx = gx - mds->res_min[0];
+ dy = gy - mds->res_min[1];
+ dz = gz - mds->res_min[2];
+ d_index = manta_get_index(dx, mds->res[0], dy, mds->res[1], dz);
+ /* make sure emission cell is inside the new domain boundary */
+ if (dx < 0 || dy < 0 || dz < 0 || dx >= mds->res[0] || dy >= mds->res[1] ||
+ dz >= mds->res[2]) {
+ continue;
+ }
+
+ if (mfs->behavior == FLUID_FLOW_BEHAVIOR_OUTFLOW) { // outflow
+ apply_outflow_fields(d_index,
+ distance_map[e_index],
+ density_in,
+ heat_in,
+ fuel_in,
+ react_in,
+ color_r_in,
+ color_g_in,
+ color_b_in,
+ phiout_in);
+ }
+ else if (mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY && mmd2->time > 2) {
+ apply_inflow_fields(mfs,
+ 0.0f,
+ FLT_MAX,
+ d_index,
+ density_in,
+ density,
+ heat_in,
+ heat,
+ fuel_in,
+ fuel,
+ react_in,
+ react,
+ color_r_in,
+ color_r,
+ color_g_in,
+ color_g,
+ color_b_in,
+ color_b,
+ phi_in,
+ emission_in);
+ }
+ else if (mfs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW ||
+ mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY) { // inflow
+ /* only apply inflow if enabled */
+ if (mfs->flags & FLUID_FLOW_USE_INFLOW) {
+ apply_inflow_fields(mfs,
+ emission_map[e_index],
+ distance_map[e_index],
+ d_index,
+ density_in,
+ density,
+ heat_in,
+ heat,
+ fuel_in,
+ fuel,
+ react_in,
+ react,
+ color_r_in,
+ color_r,
+ color_g_in,
+ color_g,
+ color_b_in,
+ color_b,
+ phi_in,
+ emission_in);
+ /* initial velocity */
+ if (mfs->flags & FLUID_FLOW_INITVELOCITY) {
+ velx_initial[d_index] = velocity_map[e_index * 3];
+ vely_initial[d_index] = velocity_map[e_index * 3 + 1];
+ velz_initial[d_index] = velocity_map[e_index * 3 + 2];
+ }
+ }
+ }
+ } // low res loop
+ }
+ }
+
+ // free emission maps
+ em_freeData(em);
+
+ } // end emission
+ }
+
+ BKE_collision_objects_free(flowobjs);
+ if (emaps) {
+ MEM_freeN(emaps);
+ }
+}
+
+typedef struct UpdateEffectorsData {
+ Scene *scene;
+ FluidDomainSettings *mds;
+ ListBase *effectors;
+
+ float *density;
+ float *fuel;
+ float *force_x;
+ float *force_y;
+ float *force_z;
+ float *velocity_x;
+ float *velocity_y;
+ float *velocity_z;
+ int *flags;
+ float *phi_obs_in;
+} UpdateEffectorsData;
+
+static void update_effectors_task_cb(void *__restrict userdata,
+ const int x,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ UpdateEffectorsData *data = userdata;
+ FluidDomainSettings *mds = data->mds;
+
+ for (int y = 0; y < mds->res[1]; y++) {
+ for (int z = 0; z < mds->res[2]; z++) {
+ EffectedPoint epoint;
+ float mag;
+ float voxel_center[3] = {0, 0, 0}, vel[3] = {0, 0, 0}, retvel[3] = {0, 0, 0};
+ const uint index = manta_get_index(x, mds->res[0], y, mds->res[1], z);
+
+ if ((data->fuel && MAX2(data->density[index], data->fuel[index]) < FLT_EPSILON) ||
+ (data->density && data->density[index] < FLT_EPSILON) ||
+ (data->phi_obs_in && data->phi_obs_in[index] < 0.0f) ||
+ data->flags[index] & 2) // mantaflow convention: 2 == FlagObstacle
+ {
+ continue;
+ }
+
+ /* get velocities from manta grid space and convert to blender units */
+ vel[0] = data->velocity_x[index];
+ vel[1] = data->velocity_y[index];
+ vel[2] = data->velocity_z[index];
+ mul_v3_fl(vel, mds->dx);
+
+ /* convert vel to global space */
+ mag = len_v3(vel);
+ mul_mat3_m4_v3(mds->obmat, vel);
+ normalize_v3(vel);
+ mul_v3_fl(vel, mag);
+
+ voxel_center[0] = mds->p0[0] + mds->cell_size[0] * ((float)(x + mds->res_min[0]) + 0.5f);
+ voxel_center[1] = mds->p0[1] + mds->cell_size[1] * ((float)(y + mds->res_min[1]) + 0.5f);
+ voxel_center[2] = mds->p0[2] + mds->cell_size[2] * ((float)(z + mds->res_min[2]) + 0.5f);
+ mul_m4_v3(mds->obmat, voxel_center);
+
+ /* do effectors */
+ pd_point_from_loc(data->scene, voxel_center, vel, index, &epoint);
+ BKE_effectors_apply(data->effectors, NULL, mds->effector_weights, &epoint, retvel, NULL);
+
+ /* convert retvel to local space */
+ mag = len_v3(retvel);
+ mul_mat3_m4_v3(mds->imat, retvel);
+ normalize_v3(retvel);
+ mul_v3_fl(retvel, mag);
+
+ /* constrain forces to interval -1 to 1 */
+ data->force_x[index] = min_ff(max_ff(-1.0f, retvel[0] * 0.2f), 1.0f);
+ data->force_y[index] = min_ff(max_ff(-1.0f, retvel[1] * 0.2f), 1.0f);
+ data->force_z[index] = min_ff(max_ff(-1.0f, retvel[2] * 0.2f), 1.0f);
+ }
+ }
+}
+
+static void update_effectors(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, FluidDomainSettings *mds, float UNUSED(dt))
+{
+ ListBase *effectors;
+ /* make sure smoke flow influence is 0.0f */
+ mds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f;
+ effectors = BKE_effectors_create(depsgraph, ob, NULL, mds->effector_weights);
+
+ if (effectors) {
+ // precalculate wind forces
+ UpdateEffectorsData data;
+ data.scene = scene;
+ data.mds = mds;
+ data.effectors = effectors;
+ data.density = manta_smoke_get_density(mds->fluid);
+ data.fuel = manta_smoke_get_fuel(mds->fluid);
+ data.force_x = manta_get_force_x(mds->fluid);
+ data.force_y = manta_get_force_y(mds->fluid);
+ data.force_z = manta_get_force_z(mds->fluid);
+ data.velocity_x = manta_get_velocity_x(mds->fluid);
+ data.velocity_y = manta_get_velocity_y(mds->fluid);
+ data.velocity_z = manta_get_velocity_z(mds->fluid);
+ data.flags = manta_smoke_get_obstacle(mds->fluid);
+ data.phi_obs_in = manta_get_phiobs_in(mds->fluid);
+
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 2;
+ BLI_task_parallel_range(0, mds->res[0], &data, update_effectors_task_cb, &settings);
+ }
+
+ BKE_effectors_free(effectors);
+}
+
+static Mesh *create_liquid_geometry(FluidDomainSettings *mds, Mesh *orgmesh, Object *ob)
+{
+ Mesh *me;
+ MVert *mverts;
+ MPoly *mpolys;
+ MLoop *mloops;
+ short *normals, *no_s;
+ float no[3];
+ float min[3];
+ float max[3];
+ float size[3];
+ float cell_size_scaled[3];
+
+ /* assign material + flags to new dm
+ * if there's no faces in original dm, keep materials and flags unchanged */
+ MPoly *mpoly;
+ MPoly mp_example = {0};
+ mpoly = orgmesh->mpoly;
+ if (mpoly) {
+ mp_example = *mpoly;
+ }
+ /* else leave NULL'd */
+
+ const short mp_mat_nr = mp_example.mat_nr;
+ const char mp_flag = mp_example.flag;
+
+ int i;
+ int num_verts, num_normals, num_faces;
+
+ if (!mds->fluid) {
+ return NULL;
+ }
+
+ num_verts = manta_liquid_get_num_verts(mds->fluid);
+ num_normals = manta_liquid_get_num_normals(mds->fluid);
+ num_faces = manta_liquid_get_num_triangles(mds->fluid);
+
+# ifdef DEBUG_PRINT
+ /* Debugging: Print number of vertices, normals, and faces. */
+ printf("num_verts: %d, num_normals: %d, num_faces: %d\n", num_verts, num_normals, num_faces);
+# endif
+
+ if (!num_verts || !num_faces) {
+ return NULL;
+ }
+
+ me = BKE_mesh_new_nomain(num_verts, 0, 0, num_faces * 3, num_faces);
+ mverts = me->mvert;
+ mpolys = me->mpoly;
+ mloops = me->mloop;
+ if (!me) {
+ return NULL;
+ }
+
+ // Get size (dimension) but considering scaling scaling
+ copy_v3_v3(cell_size_scaled, mds->cell_size);
+ mul_v3_v3(cell_size_scaled, ob->scale);
+ madd_v3fl_v3fl_v3fl_v3i(min, mds->p0, cell_size_scaled, mds->res_min);
+ madd_v3fl_v3fl_v3fl_v3i(max, mds->p0, cell_size_scaled, mds->res_max);
+ sub_v3_v3v3(size, max, min);
+
+ // Biggest dimension will be used for upscaling
+ float max_size = MAX3(size[0], size[1], size[2]);
+
+ // Vertices
+ for (i = 0; i < num_verts; i++, mverts++) {
+ // read raw data. is normalized cube around domain origin
+ mverts->co[0] = manta_liquid_get_vertex_x_at(mds->fluid, i);
+ mverts->co[1] = manta_liquid_get_vertex_y_at(mds->fluid, i);
+ mverts->co[2] = manta_liquid_get_vertex_z_at(mds->fluid, i);
+
+ // if reading raw data directly from manta, normalize now, otherwise omit this, ie when reading
+ // from files
+ {
+ // normalize to unit cube around 0
+ mverts->co[0] -= ((float)mds->res[0] * mds->mesh_scale) * 0.5f;
+ mverts->co[1] -= ((float)mds->res[1] * mds->mesh_scale) * 0.5f;
+ mverts->co[2] -= ((float)mds->res[2] * mds->mesh_scale) * 0.5f;
+ mverts->co[0] *= mds->dx / mds->mesh_scale;
+ mverts->co[1] *= mds->dx / mds->mesh_scale;
+ mverts->co[2] *= mds->dx / mds->mesh_scale;
+ }
+
+ mverts->co[0] *= max_size / fabsf(ob->scale[0]);
+ mverts->co[1] *= max_size / fabsf(ob->scale[1]);
+ mverts->co[2] *= max_size / fabsf(ob->scale[2]);
+# ifdef DEBUG_PRINT
+ /* Debugging: Print coordinates of vertices. */
+ printf("mverts->co[0]: %f, mverts->co[1]: %f, mverts->co[2]: %f\n",
+ mverts->co[0],
+ mverts->co[1],
+ mverts->co[2]);
+# endif
+ }
+
+ // Normals
+ normals = MEM_callocN(sizeof(short) * num_normals * 3, "Fluidmesh_tmp_normals");
+
+ for (i = 0, no_s = normals; i < num_normals; no_s += 3, i++) {
+ no[0] = manta_liquid_get_normal_x_at(mds->fluid, i);
+ no[1] = manta_liquid_get_normal_y_at(mds->fluid, i);
+ no[2] = manta_liquid_get_normal_z_at(mds->fluid, i);
+
+ normal_float_to_short_v3(no_s, no);
+# ifdef DEBUG_PRINT
+ /* Debugging: Print coordinates of normals. */
+ printf("no_s[0]: %d, no_s[1]: %d, no_s[2]: %d\n", no_s[0], no_s[1], no_s[2]);
+# endif
+ }
+
+ // Triangles
+ for (i = 0; i < num_faces; i++, mpolys++, mloops += 3) {
+ /* initialize from existing face */
+ mpolys->mat_nr = mp_mat_nr;
+ mpolys->flag = mp_flag;
+
+ mpolys->loopstart = i * 3;
+ mpolys->totloop = 3;
+
+ mloops[0].v = manta_liquid_get_triangle_x_at(mds->fluid, i);
+ mloops[1].v = manta_liquid_get_triangle_y_at(mds->fluid, i);
+ mloops[2].v = manta_liquid_get_triangle_z_at(mds->fluid, i);
+# ifdef DEBUG_PRINT
+ /* Debugging: Print mesh faces. */
+ printf("mloops[0].v: %d, mloops[1].v: %d, mloops[2].v: %d\n",
+ mloops[0].v,
+ mloops[1].v,
+ mloops[2].v);
+# endif
+ }
+
+ BKE_mesh_ensure_normals(me);
+ BKE_mesh_calc_edges(me, false, false);
+ BKE_mesh_vert_normals_apply(me, (short(*)[3])normals);
+
+ MEM_freeN(normals);
+
+ /* return early if no mesh vert velocities required */
+ if ((mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) == 0) {
+ return me;
+ }
+
+ if (mds->mesh_velocities) {
+ MEM_freeN(mds->mesh_velocities);
+ }
+
+ mds->mesh_velocities = MEM_calloc_arrayN(
+ num_verts, sizeof(FluidDomainVertexVelocity), "Fluidmesh_vertvelocities");
+ mds->totvert = num_verts;
+
+ FluidDomainVertexVelocity *velarray = NULL;
+ velarray = mds->mesh_velocities;
+
+ float time_mult = 25.f * DT_DEFAULT;
+
+ for (i = 0; i < num_verts; i++, mverts++) {
+ velarray[i].vel[0] = manta_liquid_get_vertvel_x_at(mds->fluid, i) * (mds->dx / time_mult);
+ velarray[i].vel[1] = manta_liquid_get_vertvel_y_at(mds->fluid, i) * (mds->dx / time_mult);
+ velarray[i].vel[2] = manta_liquid_get_vertvel_z_at(mds->fluid, i) * (mds->dx / time_mult);
+# ifdef DEBUG_PRINT
+ /* Debugging: Print velocities of vertices. */
+ printf("velarray[%d].vel[0]: %f, velarray[%d].vel[1]: %f, velarray[%d].vel[2]: %f\n",
+ i,
+ velarray[i].vel[0],
+ i,
+ velarray[i].vel[1],
+ i,
+ velarray[i].vel[2]);
+# endif
+ }
+
+ return me;
+}
+
+static Mesh *create_smoke_geometry(FluidDomainSettings *mds, Mesh *orgmesh, Object *ob)
+{
+ Mesh *result;
+ MVert *mverts;
+ MPoly *mpolys;
+ MLoop *mloops;
+ float min[3];
+ float max[3];
+ float *co;
+ MPoly *mp;
+ MLoop *ml;
+
+ int num_verts = 8;
+ int num_faces = 6;
+ int i;
+ float ob_loc[3] = {0};
+ float ob_cache_loc[3] = {0};
+
+ /* Just copy existing mesh if there is no content or if the adaptive domain is not being used. */
+ if (mds->total_cells <= 1 || (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) == 0) {
+ return BKE_mesh_copy_for_eval(orgmesh, false);
+ }
+
+ result = BKE_mesh_new_nomain(num_verts, 0, 0, num_faces * 4, num_faces);
+ mverts = result->mvert;
+ mpolys = result->mpoly;
+ mloops = result->mloop;
+
+ if (num_verts) {
+ /* Volume bounds. */
+ madd_v3fl_v3fl_v3fl_v3i(min, mds->p0, mds->cell_size, mds->res_min);
+ madd_v3fl_v3fl_v3fl_v3i(max, mds->p0, mds->cell_size, mds->res_max);
+
+ /* Set vertices of smoke BB. Especially important, when BB changes (adaptive domain). */
+ /* Top slab */
+ co = mverts[0].co;
+ co[0] = min[0];
+ co[1] = min[1];
+ co[2] = max[2];
+ co = mverts[1].co;
+ co[0] = max[0];
+ co[1] = min[1];
+ co[2] = max[2];
+ co = mverts[2].co;
+ co[0] = max[0];
+ co[1] = max[1];
+ co[2] = max[2];
+ co = mverts[3].co;
+ co[0] = min[0];
+ co[1] = max[1];
+ co[2] = max[2];
+ /* Bottom slab. */
+ co = mverts[4].co;
+ co[0] = min[0];
+ co[1] = min[1];
+ co[2] = min[2];
+ co = mverts[5].co;
+ co[0] = max[0];
+ co[1] = min[1];
+ co[2] = min[2];
+ co = mverts[6].co;
+ co[0] = max[0];
+ co[1] = max[1];
+ co[2] = min[2];
+ co = mverts[7].co;
+ co[0] = min[0];
+ co[1] = max[1];
+ co[2] = min[2];
+
+ /* Create faces. */
+ /* Top side. */
+ mp = &mpolys[0];
+ ml = &mloops[0 * 4];
+ mp->loopstart = 0 * 4;
+ mp->totloop = 4;
+ ml[0].v = 0;
+ ml[1].v = 1;
+ ml[2].v = 2;
+ ml[3].v = 3;
+ /* Right side. */
+ mp = &mpolys[1];
+ ml = &mloops[1 * 4];
+ mp->loopstart = 1 * 4;
+ mp->totloop = 4;
+ ml[0].v = 2;
+ ml[1].v = 1;
+ ml[2].v = 5;
+ ml[3].v = 6;
+ /* Bottom side. */
+ mp = &mpolys[2];
+ ml = &mloops[2 * 4];
+ mp->loopstart = 2 * 4;
+ mp->totloop = 4;
+ ml[0].v = 7;
+ ml[1].v = 6;
+ ml[2].v = 5;
+ ml[3].v = 4;
+ /* Left side. */
+ mp = &mpolys[3];
+ ml = &mloops[3 * 4];
+ mp->loopstart = 3 * 4;
+ mp->totloop = 4;
+ ml[0].v = 0;
+ ml[1].v = 3;
+ ml[2].v = 7;
+ ml[3].v = 4;
+ /* Front side. */
+ mp = &mpolys[4];
+ ml = &mloops[4 * 4];
+ mp->loopstart = 4 * 4;
+ mp->totloop = 4;
+ ml[0].v = 3;
+ ml[1].v = 2;
+ ml[2].v = 6;
+ ml[3].v = 7;
+ /* Back side. */
+ mp = &mpolys[5];
+ ml = &mloops[5 * 4];
+ mp->loopstart = 5 * 4;
+ mp->totloop = 4;
+ ml[0].v = 1;
+ ml[1].v = 0;
+ ml[2].v = 4;
+ ml[3].v = 5;
+
+ /* Calculate required shift to match domain's global position
+ * it was originally simulated at (if object moves without manta step). */
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->obmat, ob_loc);
+ mul_m4_v3(mds->obmat, ob_cache_loc);
+ sub_v3_v3v3(mds->obj_shift_f, ob_cache_loc, ob_loc);
+ /* Convert shift to local space and apply to vertices. */
+ mul_mat3_m4_v3(ob->imat, mds->obj_shift_f);
+ /* Apply shift to vertices. */
+ for (i = 0; i < num_verts; i++) {
+ add_v3_v3(mverts[i].co, mds->obj_shift_f);
+ }
+ }
+
+ BKE_mesh_calc_edges(result, false, false);
+ result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
+ return result;
+}
+
+static void manta_step(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me, FluidModifierData *mmd, int frame)
+{
+ FluidDomainSettings *mds = mmd->domain;
+ float dt, frame_length, time_total;
+ float time_per_frame;
+ bool init_resolution = true;
+
+ /* update object state */
+ invert_m4_m4(mds->imat, ob->obmat);
+ copy_m4_m4(mds->obmat, ob->obmat);
+
+ /* gas domain might use adaptive domain */
+ if (mds->type == FLUID_DOMAIN_TYPE_GAS) {
+ init_resolution = (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) != 0;
+ }
+ manta_set_domain_from_mesh(mds, ob, me, init_resolution);
+
+ /* use local variables for adaptive loop, dt can change */
+ frame_length = mds->frame_length;
+ dt = mds->dt;
+ time_per_frame = 0;
+ time_total = mds->time_total;
+
+ BLI_mutex_lock(&object_update_lock);
+
+ /* loop as long as time_per_frame (sum of sub dt's) does not exceed actual framelength */
+ while (time_per_frame < frame_length) {
+ manta_adapt_timestep(mds->fluid);
+ dt = manta_get_timestep(mds->fluid);
+
+ /* save adapted dt so that MANTA object can access it (important when adaptive domain creates
+ * new MANTA object) */
+ mds->dt = dt;
+
+ /* count for how long this while loop is running */
+ time_per_frame += dt;
+ time_total += dt;
+
+ /* Calculate inflow geometry */
+ update_flowsfluids(depsgraph, scene, ob, mds, time_per_frame, frame_length, frame, dt);
+
+ manta_update_variables(mds->fluid, mmd);
+
+ /* Calculate obstacle geometry */
+ update_obstacles(depsgraph, scene, ob, mds, time_per_frame, frame_length, frame, dt);
+
+ if (mds->total_cells > 1) {
+ update_effectors(depsgraph, scene, ob, mds, dt);
+ manta_bake_data(mds->fluid, mmd, frame);
+
+ mds->time_per_frame = time_per_frame;
+ mds->time_total = time_total;
+ }
+ }
+
+ if (mds->type == FLUID_DOMAIN_TYPE_GAS) {
+ manta_smoke_calc_transparency(mds, DEG_get_evaluated_view_layer(depsgraph));
+ }
+ BLI_mutex_unlock(&object_update_lock);
+}
+
+static void manta_guiding(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, FluidModifierData *mmd, int frame)
+{
+ FluidDomainSettings *mds = mmd->domain;
+ float fps = scene->r.frs_sec / scene->r.frs_sec_base;
+ float dt = DT_DEFAULT * (25.0f / fps) * mds->time_scale;
+ ;
+
+ BLI_mutex_lock(&object_update_lock);
+
+ update_obstacles(depsgraph, scene, ob, mds, dt, dt, frame, dt);
+ manta_bake_guiding(mds->fluid, mmd, frame);
+
+ BLI_mutex_unlock(&object_update_lock);
+}
+
+static void BKE_fluid_modifier_processFlow(FluidModifierData *mmd,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ Mesh *me,
+ const int scene_framenr)
+{
+ if (scene_framenr >= mmd->time) {
+ BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me);
+ }
+
+ if (mmd->flow) {
+ if (mmd->flow->mesh) {
+ BKE_id_free(NULL, mmd->flow->mesh);
+ }
+ mmd->flow->mesh = BKE_mesh_copy_for_eval(me, false);
+ }
+
+ if (scene_framenr > mmd->time) {
+ mmd->time = scene_framenr;
+ }
+ else if (scene_framenr < mmd->time) {
+ mmd->time = scene_framenr;
+ BKE_fluid_modifier_reset_ex(mmd, false);
+ }
+}
+
+static void BKE_fluid_modifier_processEffector(FluidModifierData *mmd,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ Mesh *me,
+ const int scene_framenr)
+{
+ if (scene_framenr >= mmd->time) {
+ BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me);
+ }
+
+ if (mmd->effector) {
+ if (mmd->effector->mesh) {
+ BKE_id_free(NULL, mmd->effector->mesh);
+ }
+ mmd->effector->mesh = BKE_mesh_copy_for_eval(me, false);
+ }
+
+ if (scene_framenr > mmd->time) {
+ mmd->time = scene_framenr;
+ }
+ else if (scene_framenr < mmd->time) {
+ mmd->time = scene_framenr;
+ BKE_fluid_modifier_reset_ex(mmd, false);
+ }
+}
+
+static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ Mesh *me,
+ const int scene_framenr)
+{
+ FluidDomainSettings *mds = mmd->domain;
+ Object *guide_parent = NULL;
+ Object **objs = NULL;
+ uint numobj = 0;
+ FluidModifierData *mmd_parent = NULL;
+
+ bool is_startframe;
+ is_startframe = (scene_framenr == mds->cache_frame_start);
+
+ /* Reset fluid if no fluid present (obviously)
+ * or if timeline gets reset to startframe */
+ if (!mds->fluid || is_startframe) {
+ BKE_fluid_modifier_reset_ex(mmd, false);
+ }
+
+ BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me);
+
+ /* ensure that time parameters are initialized correctly before every step */
+ float fps = scene->r.frs_sec / scene->r.frs_sec_base;
+ mds->frame_length = DT_DEFAULT * (25.0f / fps) * mds->time_scale;
+ mds->dt = mds->frame_length;
+ mds->time_per_frame = 0;
+ mds->time_total = (scene_framenr - 1) * mds->frame_length;
+
+ /* Guiding parent res pointer needs initialization */
+ guide_parent = mds->guide_parent;
+ if (guide_parent) {
+ mmd_parent = (FluidModifierData *)modifiers_findByType(guide_parent, eModifierType_Fluid);
+ if (mmd_parent->domain) {
+ copy_v3_v3_int(mds->guide_res, mmd_parent->domain->res);
+ }
+ }
+
+ objs = BKE_collision_objects_create(
+ depsgraph, ob, mds->fluid_group, &numobj, eModifierType_Fluid);
+ update_flowsflags(mds, objs, numobj);
+ if (objs) {
+ MEM_freeN(objs);
+ }
+
+ objs = BKE_collision_objects_create(
+ depsgraph, ob, mds->effector_group, &numobj, eModifierType_Fluid);
+ update_obstacleflags(mds, objs, numobj);
+ if (objs) {
+ MEM_freeN(objs);
+ }
+
+ /* Ensure cache directory is not relative */
+ const char *relbase = modifier_path_relbase_from_global(ob);
+ BLI_path_abs(mds->cache_directory, relbase);
+
+ int data_frame = scene_framenr, noise_frame = scene_framenr;
+ int mesh_frame = scene_framenr, particles_frame = scene_framenr, guide_frame = scene_framenr;
+
+ bool with_smoke, with_liquid;
+ with_smoke = mds->type == FLUID_DOMAIN_TYPE_GAS;
+ with_liquid = mds->type == FLUID_DOMAIN_TYPE_LIQUID;
+
+ bool drops, bubble, floater;
+ drops = mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
+ bubble = mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
+ floater = mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
+
+ bool with_script, with_adaptive, with_noise, with_mesh, with_particles, with_guide;
+ with_script = mds->flags & FLUID_DOMAIN_EXPORT_MANTA_SCRIPT;
+ with_adaptive = mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN;
+ with_noise = mds->flags & FLUID_DOMAIN_USE_NOISE;
+ with_mesh = mds->flags & FLUID_DOMAIN_USE_MESH;
+ with_guide = mds->flags & FLUID_DOMAIN_USE_GUIDE;
+ with_particles = drops || bubble || floater;
+
+ bool has_data, has_noise, has_mesh, has_particles, has_guide;
+ has_data = has_noise = has_mesh = has_particles = has_guide = false;
+
+ bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide, bake_outdated;
+ baking_data = mds->cache_flag & FLUID_DOMAIN_BAKING_DATA;
+ baking_noise = mds->cache_flag & FLUID_DOMAIN_BAKING_NOISE;
+ baking_mesh = mds->cache_flag & FLUID_DOMAIN_BAKING_MESH;
+ baking_particles = mds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES;
+ baking_guide = mds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE;
+ bake_outdated = mds->cache_flag &
+ (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_NOISE | FLUID_DOMAIN_OUTDATED_MESH |
+ FLUID_DOMAIN_OUTDATED_PARTICLES | FLUID_DOMAIN_OUTDATED_GUIDE);
+
+ bool resume_data, resume_noise, resume_mesh, resume_particles, resume_guide;
+ resume_data = (!is_startframe) && (mds->cache_frame_pause_data == scene_framenr);
+ resume_noise = (!is_startframe) && (mds->cache_frame_pause_noise == scene_framenr);
+ resume_mesh = (!is_startframe) && (mds->cache_frame_pause_mesh == scene_framenr);
+ resume_particles = (!is_startframe) && (mds->cache_frame_pause_particles == scene_framenr);
+ resume_guide = (!is_startframe) && (mds->cache_frame_pause_guide == scene_framenr);
+
+ bool read_cache, bake_cache;
+ read_cache = false, bake_cache = baking_data || baking_noise || baking_mesh || baking_particles;
+
+ bool with_gdomain;
+ with_gdomain = (mds->guide_source == FLUID_DOMAIN_GUIDE_SRC_DOMAIN);
+
+ int o_res[3], o_min[3], o_max[3], o_shift[3];
+ int mode = mds->cache_type;
+ int prev_frame = scene_framenr - 1;
+
+ /* Ensure positivity of previous frame. */
+ CLAMP(prev_frame, 1, prev_frame);
+
+ /* Cache mode specific settings */
+ switch (mode) {
+ case FLUID_DOMAIN_CACHE_FINAL:
+ /* Just load the data that has already been baked */
+ if (!baking_data && !baking_noise && !baking_mesh && !baking_particles) {
+ read_cache = true;
+ bake_cache = false;
+ }
+ break;
+ case FLUID_DOMAIN_CACHE_MODULAR:
+ /* Just load the data that has already been baked */
+ if (!baking_data && !baking_noise && !baking_mesh && !baking_particles) {
+ read_cache = true;
+ bake_cache = false;
+ break;
+ }
+
+ /* Set to previous frame if the bake was resumed
+ * ie don't read all of the already baked frames, just the one before bake resumes */
+ if (baking_data && resume_data) {
+ data_frame = prev_frame;
+ }
+ if (baking_noise && resume_noise) {
+ noise_frame = prev_frame;
+ }
+ if (baking_mesh && resume_mesh) {
+ mesh_frame = prev_frame;
+ }
+ if (baking_particles && resume_particles) {
+ particles_frame = prev_frame;
+ }
+ if (baking_guide && resume_guide) {
+ guide_frame = prev_frame;
+ }
+
+ /* Noise, mesh and particles can never be baked more than data. */
+ CLAMP(noise_frame, noise_frame, data_frame);
+ CLAMP(mesh_frame, mesh_frame, data_frame);
+ CLAMP(particles_frame, particles_frame, data_frame);
+ CLAMP(guide_frame, guide_frame, mds->cache_frame_end);
+
+ /* Force to read cache as we're resuming the bake */
+ read_cache = true;
+ break;
+ case FLUID_DOMAIN_CACHE_REPLAY:
+ default:
+ /* Always trying to read the cache in replay mode. */
+ read_cache = true;
+ break;
+ }
+
+ /* Cache outdated? If so reset, don't read, and then just rebake.
+ * Note: Only do this in replay mode! */
+ bool mode_replay = (mode == FLUID_DOMAIN_CACHE_REPLAY);
+ if (bake_outdated && mode_replay) {
+ read_cache = false;
+ bake_cache = true;
+ BKE_fluid_cache_free(mds, ob, mds->cache_flag);
+ }
+
+ /* Try to read from cache and keep track of read success. */
+ if (read_cache) {
+
+ /* Read mesh cache. */
+ if (with_liquid && with_mesh) {
+ has_mesh = manta_read_mesh(mds->fluid, mmd, mesh_frame);
+ }
+
+ /* Read particles cache. */
+ if (with_liquid && with_particles) {
+ has_particles = manta_read_particles(mds->fluid, mmd, particles_frame);
+ }
+
+ /* Read guide cache. */
+ if (with_guide) {
+ FluidModifierData *mmd2 = (with_gdomain) ? mmd_parent : mmd;
+ has_guide = manta_read_guiding(mds->fluid, mmd2, scene_framenr, with_gdomain);
+ }
+
+ /* Read noise and data cache */
+ if (with_smoke && with_noise) {
+
+ /* Only reallocate when just reading cache or when resuming during bake. */
+ if ((!baking_noise || (baking_noise && resume_noise)) &&
+ manta_read_config(mds->fluid, mmd, noise_frame) &&
+ manta_needs_realloc(mds->fluid, mmd)) {
+ BKE_fluid_reallocate_fluid(mds, mds->res, 1);
+ }
+ has_noise = manta_read_noise(mds->fluid, mmd, noise_frame);
+
+ /* In case of using the adaptive domain, copy all data that was read to a new fluid object.
+ */
+ if (with_adaptive && baking_noise) {
+ /* Adaptive domain needs to know about current state, so save it, then copy. */
+ copy_v3_v3_int(o_res, mds->res);
+ copy_v3_v3_int(o_min, mds->res_min);
+ copy_v3_v3_int(o_max, mds->res_max);
+ copy_v3_v3_int(o_shift, mds->shift);
+ if (manta_read_config(mds->fluid, mmd, data_frame) &&
+ manta_needs_realloc(mds->fluid, mmd)) {
+ BKE_fluid_reallocate_copy_fluid(
+ mds, o_res, mds->res, o_min, mds->res_min, o_max, o_shift, mds->shift);
+ }
+ }
+ has_data = manta_read_data(mds->fluid, mmd, data_frame);
+ }
+ /* Read data cache only */
+ else {
+ /* Read config and realloc fluid object if needed. */
+ if (manta_read_config(mds->fluid, mmd, data_frame) && manta_needs_realloc(mds->fluid, mmd)) {
+ BKE_fluid_reallocate_fluid(mds, mds->res, 1);
+ }
+ /* Read data cache */
+ has_data = manta_read_data(mds->fluid, mmd, data_frame);
+ }
+ }
+
+ /* Cache mode specific settings */
+ switch (mode) {
+ case FLUID_DOMAIN_CACHE_FINAL:
+ case FLUID_DOMAIN_CACHE_MODULAR:
+ break;
+ case FLUID_DOMAIN_CACHE_REPLAY:
+ default:
+ baking_data = !has_data;
+ if (with_smoke && with_noise) {
+ baking_noise = !has_noise;
+ }
+ if (with_liquid && with_mesh) {
+ baking_mesh = !has_mesh;
+ }
+ if (with_liquid && with_particles) {
+ baking_particles = !has_particles;
+ }
+
+ bake_cache = baking_data || baking_noise || baking_mesh || baking_particles;
+ break;
+ }
+
+ /* Trigger bake calls individually */
+ if (bake_cache) {
+ /* Ensure fresh variables at every animation step */
+ manta_update_variables(mds->fluid, mmd);
+
+ /* Export mantaflow python script on first frame (once only) and for any bake type */
+ if (with_script && is_startframe) {
+ if (with_smoke) {
+ manta_smoke_export_script(mmd->domain->fluid, mmd);
+ }
+ if (with_liquid) {
+ manta_liquid_export_script(mmd->domain->fluid, mmd);
+ }
+ }
+
+ if (baking_guide && with_guide) {
+ manta_guiding(depsgraph, scene, ob, mmd, scene_framenr);
+ }
+ if (baking_data) {
+ manta_step(depsgraph, scene, ob, me, mmd, scene_framenr);
+ manta_write_config(mds->fluid, mmd, scene_framenr);
+ manta_write_data(mds->fluid, mmd, scene_framenr);
+ }
+ if (has_data || baking_data) {
+ if (baking_noise && with_smoke && with_noise) {
+ manta_bake_noise(mds->fluid, mmd, scene_framenr);
+ }
+ if (baking_mesh && with_liquid && with_mesh) {
+ manta_bake_mesh(mds->fluid, mmd, scene_framenr);
+ }
+ if (baking_particles && with_liquid && with_particles) {
+ manta_bake_particles(mds->fluid, mmd, scene_framenr);
+ }
+ }
+ }
+ mmd->time = scene_framenr;
+}
+
+static void BKE_fluid_modifier_process(
+ FluidModifierData *mmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me)
+{
+ const int scene_framenr = (int)DEG_get_ctime(depsgraph);
+
+ if ((mmd->type & MOD_FLUID_TYPE_FLOW)) {
+ BKE_fluid_modifier_processFlow(mmd, depsgraph, scene, ob, me, scene_framenr);
+ }
+ else if (mmd->type & MOD_FLUID_TYPE_EFFEC) {
+ BKE_fluid_modifier_processEffector(mmd, depsgraph, scene, ob, me, scene_framenr);
+ }
+ else if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ BKE_fluid_modifier_processDomain(mmd, depsgraph, scene, ob, me, scene_framenr);
+ }
+}
+
+struct Mesh *BKE_fluid_modifier_do(
+ FluidModifierData *mmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me)
+{
+ /* Lock so preview render does not read smoke data while it gets modified. */
+ if ((mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
+ BLI_rw_mutex_lock(mmd->domain->fluid_mutex, THREAD_LOCK_WRITE);
+ }
+
+ BKE_fluid_modifier_process(mmd, depsgraph, scene, ob, me);
+
+ if ((mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
+ BLI_rw_mutex_unlock(mmd->domain->fluid_mutex);
+ }
+
+ Mesh *result = NULL;
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN && mmd->domain) {
+ /* Return generated geometry depending on domain type. */
+ if (mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) {
+ result = create_liquid_geometry(mmd->domain, me, ob);
+ }
+ if (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
+ result = create_smoke_geometry(mmd->domain, me, ob);
+ }
+ /* Clear flag outside of locked block (above). */
+ mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_DATA;
+ mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_NOISE;
+ mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_MESH;
+ mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_PARTICLES;
+ mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_GUIDE;
+ }
+ if (!result) {
+ result = BKE_mesh_copy_for_eval(me, false);
+ }
+ else {
+ BKE_mesh_copy_settings(result, me);
+ }
+
+ /* Liquid simulation has a texture space that based on the bounds of the fluid mesh.
+ * This does not seem particularly useful, but it's backwards compatible.
+ *
+ * Smoke simulation needs a texture space relative to the adaptive domain bounds, not the
+ * original mesh. So recompute it at this point in the modifier stack. See T58492. */
+ BKE_mesh_texspace_calc(result);
+
+ return result;
+}
+
+static float calc_voxel_transp(
+ float *result, float *input, int res[3], int *pixel, float *t_ray, float correct)
+{
+ const size_t index = manta_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]);
+
+ // T_ray *= T_vox
+ *t_ray *= expf(input[index] * correct);
+
+ if (result[index] < 0.0f) {
+ result[index] = *t_ray;
+ }
+
+ return *t_ray;
+}
+
+static void bresenham_linie_3D(int x1,
+ int y1,
+ int z1,
+ int x2,
+ int y2,
+ int z2,
+ float *t_ray,
+ BKE_Fluid_BresenhamFn cb,
+ float *result,
+ float *input,
+ int res[3],
+ float correct)
+{
+ int dx, dy, dz, i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2;
+ int pixel[3];
+
+ pixel[0] = x1;
+ pixel[1] = y1;
+ pixel[2] = z1;
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+ dz = z2 - z1;
+
+ x_inc = (dx < 0) ? -1 : 1;
+ l = abs(dx);
+ y_inc = (dy < 0) ? -1 : 1;
+ m = abs(dy);
+ z_inc = (dz < 0) ? -1 : 1;
+ n = abs(dz);
+ dx2 = l << 1;
+ dy2 = m << 1;
+ dz2 = n << 1;
+
+ if ((l >= m) && (l >= n)) {
+ err_1 = dy2 - l;
+ err_2 = dz2 - l;
+ for (i = 0; i < l; i++) {
+ if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
+ break;
+ }
+ if (err_1 > 0) {
+ pixel[1] += y_inc;
+ err_1 -= dx2;
+ }
+ if (err_2 > 0) {
+ pixel[2] += z_inc;
+ err_2 -= dx2;
+ }
+ err_1 += dy2;
+ err_2 += dz2;
+ pixel[0] += x_inc;
+ }
+ }
+ else if ((m >= l) && (m >= n)) {
+ err_1 = dx2 - m;
+ err_2 = dz2 - m;
+ for (i = 0; i < m; i++) {
+ if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
+ break;
+ }
+ if (err_1 > 0) {
+ pixel[0] += x_inc;
+ err_1 -= dy2;
+ }
+ if (err_2 > 0) {
+ pixel[2] += z_inc;
+ err_2 -= dy2;
+ }
+ err_1 += dx2;
+ err_2 += dz2;
+ pixel[1] += y_inc;
+ }
+ }
+ else {
+ err_1 = dy2 - n;
+ err_2 = dx2 - n;
+ for (i = 0; i < n; i++) {
+ if (cb(result, input, res, pixel, t_ray, correct) <= FLT_EPSILON) {
+ break;
+ }
+ if (err_1 > 0) {
+ pixel[1] += y_inc;
+ err_1 -= dz2;
+ }
+ if (err_2 > 0) {
+ pixel[0] += x_inc;
+ err_2 -= dz2;
+ }
+ err_1 += dy2;
+ err_2 += dx2;
+ pixel[2] += z_inc;
+ }
+ }
+ cb(result, input, res, pixel, t_ray, correct);
+}
+
+static void manta_smoke_calc_transparency(FluidDomainSettings *mds, ViewLayer *view_layer)
+{
+ float bv[6] = {0};
+ float light[3];
+ int a, z, slabsize = mds->res[0] * mds->res[1], size = mds->res[0] * mds->res[1] * mds->res[2];
+ float *density = manta_smoke_get_density(mds->fluid);
+ float *shadow = manta_smoke_get_shadow(mds->fluid);
+ float correct = -7.0f * mds->dx;
+
+ if (!get_light(view_layer, light)) {
+ return;
+ }
+
+ /* convert light pos to sim cell space */
+ mul_m4_v3(mds->imat, light);
+ light[0] = (light[0] - mds->p0[0]) / mds->cell_size[0] - 0.5f - (float)mds->res_min[0];
+ light[1] = (light[1] - mds->p0[1]) / mds->cell_size[1] - 0.5f - (float)mds->res_min[1];
+ light[2] = (light[2] - mds->p0[2]) / mds->cell_size[2] - 0.5f - (float)mds->res_min[2];
+
+ for (a = 0; a < size; a++) {
+ shadow[a] = -1.0f;
+ }
+
+ /* calculate domain bounds in sim cell space */
+ // 0,2,4 = 0.0f
+ bv[1] = (float)mds->res[0]; // x
+ bv[3] = (float)mds->res[1]; // y
+ bv[5] = (float)mds->res[2]; // z
+
+ for (z = 0; z < mds->res[2]; z++) {
+ size_t index = z * slabsize;
+ int x, y;
+
+ for (y = 0; y < mds->res[1]; y++) {
+ for (x = 0; x < mds->res[0]; x++, index++) {
+ float voxel_center[3];
+ float pos[3];
+ int cell[3];
+ float t_ray = 1.0;
+
+ if (shadow[index] >= 0.0f) {
+ continue;
+ }
+ voxel_center[0] = (float)x;
+ voxel_center[1] = (float)y;
+ voxel_center[2] = (float)z;
+
+ // get starting cell (light pos)
+ if (BLI_bvhtree_bb_raycast(bv, light, voxel_center, pos) > FLT_EPSILON) {
+ // we're ouside -> use point on side of domain
+ cell[0] = (int)floor(pos[0]);
+ cell[1] = (int)floor(pos[1]);
+ cell[2] = (int)floor(pos[2]);
+ }
+ else {
+ // we're inside -> use light itself
+ cell[0] = (int)floor(light[0]);
+ cell[1] = (int)floor(light[1]);
+ cell[2] = (int)floor(light[2]);
+ }
+ /* clamp within grid bounds */
+ CLAMP(cell[0], 0, mds->res[0] - 1);
+ CLAMP(cell[1], 0, mds->res[1] - 1);
+ CLAMP(cell[2], 0, mds->res[2] - 1);
+
+ bresenham_linie_3D(cell[0],
+ cell[1],
+ cell[2],
+ x,
+ y,
+ z,
+ &t_ray,
+ calc_voxel_transp,
+ shadow,
+ density,
+ mds->res,
+ correct);
+
+ // convention -> from a RGBA float array, use G value for t_ray
+ shadow[index] = t_ray;
+ }
+ }
+ }
+}
+
+/* get smoke velocity and density at given coordinates
+ * returns fluid density or -1.0f if outside domain. */
+float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3])
+{
+ FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ zero_v3(velocity);
+
+ if (mmd && (mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain && mmd->domain->fluid) {
+ FluidDomainSettings *mds = mmd->domain;
+ float time_mult = 25.f * DT_DEFAULT;
+ float vel_mag;
+ float *velX = manta_get_velocity_x(mds->fluid);
+ float *velY = manta_get_velocity_y(mds->fluid);
+ float *velZ = manta_get_velocity_z(mds->fluid);
+ float density = 0.0f, fuel = 0.0f;
+ float pos[3];
+ copy_v3_v3(pos, position);
+ manta_pos_to_cell(mds, pos);
+
+ /* check if point is outside domain max bounds */
+ if (pos[0] < mds->res_min[0] || pos[1] < mds->res_min[1] || pos[2] < mds->res_min[2]) {
+ return -1.0f;
+ }
+ if (pos[0] > mds->res_max[0] || pos[1] > mds->res_max[1] || pos[2] > mds->res_max[2]) {
+ return -1.0f;
+ }
+
+ /* map pos between 0.0 - 1.0 */
+ pos[0] = (pos[0] - mds->res_min[0]) / ((float)mds->res[0]);
+ pos[1] = (pos[1] - mds->res_min[1]) / ((float)mds->res[1]);
+ pos[2] = (pos[2] - mds->res_min[2]) / ((float)mds->res[2]);
+
+ /* check if point is outside active area */
+ if (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS &&
+ mmd->domain->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
+ if (pos[0] < 0.0f || pos[1] < 0.0f || pos[2] < 0.0f) {
+ return 0.0f;
+ }
+ if (pos[0] > 1.0f || pos[1] > 1.0f || pos[2] > 1.0f) {
+ return 0.0f;
+ }
+ }
+
+ /* get interpolated velocity */
+ velocity[0] = BLI_voxel_sample_trilinear(velX, mds->res, pos) * mds->global_size[0] *
+ time_mult;
+ velocity[1] = BLI_voxel_sample_trilinear(velY, mds->res, pos) * mds->global_size[1] *
+ time_mult;
+ velocity[2] = BLI_voxel_sample_trilinear(velZ, mds->res, pos) * mds->global_size[2] *
+ time_mult;
+
+ /* convert velocity direction to global space */
+ vel_mag = len_v3(velocity);
+ mul_mat3_m4_v3(mds->obmat, velocity);
+ normalize_v3(velocity);
+ mul_v3_fl(velocity, vel_mag);
+
+ /* use max value of fuel or smoke density */
+ density = BLI_voxel_sample_trilinear(manta_smoke_get_density(mds->fluid), mds->res, pos);
+ if (manta_smoke_has_fuel(mds->fluid)) {
+ fuel = BLI_voxel_sample_trilinear(manta_smoke_get_fuel(mds->fluid), mds->res, pos);
+ }
+ return MAX2(density, fuel);
+ }
+ return -1.0f;
+}
+
+int BKE_fluid_get_data_flags(FluidDomainSettings *mds)
+{
+ int flags = 0;
+
+ if (mds->fluid) {
+ if (manta_smoke_has_heat(mds->fluid)) {
+ flags |= FLUID_DOMAIN_ACTIVE_HEAT;
+ }
+ if (manta_smoke_has_fuel(mds->fluid)) {
+ flags |= FLUID_DOMAIN_ACTIVE_FIRE;
+ }
+ if (manta_smoke_has_colors(mds->fluid)) {
+ flags |= FLUID_DOMAIN_ACTIVE_COLORS;
+ }
+ }
+
+ return flags;
+}
+
+void BKE_fluid_particle_system_create(struct Main *bmain,
+ struct Object *ob,
+ const char *pset_name,
+ const char *parts_name,
+ const char *psys_name,
+ const int psys_type)
+{
+ ParticleSystem *psys;
+ ParticleSettings *part;
+ ParticleSystemModifierData *pmmd;
+
+ /* add particle system */
+ part = BKE_particlesettings_add(bmain, pset_name);
+ psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
+
+ part->type = psys_type;
+ part->totpart = 0;
+ part->draw_size = 0.01f; // make fluid particles more subtle in viewport
+ part->draw_col = PART_DRAW_COL_VEL;
+ psys->part = part;
+ psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
+ BLI_strncpy(psys->name, parts_name, sizeof(psys->name));
+ BLI_addtail(&ob->particlesystem, psys);
+
+ /* add modifier */
+ pmmd = (ParticleSystemModifierData *)modifier_new(eModifierType_ParticleSystem);
+ BLI_strncpy(pmmd->modifier.name, psys_name, sizeof(pmmd->modifier.name));
+ pmmd->psys = psys;
+ BLI_addtail(&ob->modifiers, pmmd);
+ modifier_unique_name(&ob->modifiers, (ModifierData *)pmmd);
+}
+
+void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_type)
+{
+ ParticleSystemModifierData *pmmd;
+ ParticleSystem *psys, *next_psys;
+
+ for (psys = ob->particlesystem.first; psys; psys = next_psys) {
+ next_psys = psys->next;
+ if (psys->part->type & particle_type) {
+ /* clear modifier */
+ pmmd = psys_get_modifier(ob, psys);
+ BLI_remlink(&ob->modifiers, pmmd);
+ modifier_free((ModifierData *)pmmd);
+
+ /* clear particle system */
+ BLI_remlink(&ob->particlesystem, psys);
+ psys_free(ob, psys);
+ }
+ }
+}
+
+#endif /* WITH_FLUID */
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
deleted file mode 100644
index 994e00f227a..00000000000
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- */
-
-/** \file
- * \ingroup bke
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-
-#include "BLI_math.h"
-
-#include "BKE_customdata.h"
-#include "BKE_fluidsim.h"
-#include "BKE_library.h"
-#include "BKE_mesh_runtime.h"
-
-/* ************************* fluidsim bobj file handling **************************** */
-
-//-------------------------------------------------------------------------------
-// file handling
-//-------------------------------------------------------------------------------
-
-void initElbeemMesh(struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- int *numVertices,
- float **vertices,
- int *numTriangles,
- int **triangles,
- int useGlobalCoords,
- int modifierIndex)
-{
- Mesh *mesh;
- const MVert *mvert;
- const MLoop *mloop;
- const MLoopTri *looptri, *lt;
- int i, mvert_num, looptri_num;
- float *verts;
- int *tris;
-
- mesh = mesh_create_eval_final_index_render(
- depsgraph, scene, ob, &CD_MASK_BAREMESH, modifierIndex);
-
- mvert = mesh->mvert;
- mloop = mesh->mloop;
- looptri = BKE_mesh_runtime_looptri_ensure(mesh);
- mvert_num = mesh->totvert;
- looptri_num = mesh->runtime.looptris.len;
-
- *numVertices = mvert_num;
- verts = MEM_mallocN(mvert_num * sizeof(float[3]), "elbeemmesh_vertices");
- for (i = 0; i < mvert_num; i++) {
- copy_v3_v3(&verts[i * 3], mvert[i].co);
- if (useGlobalCoords) {
- mul_m4_v3(ob->obmat, &verts[i * 3]);
- }
- }
- *vertices = verts;
-
- *numTriangles = looptri_num;
- tris = MEM_mallocN(looptri_num * sizeof(int[3]), "elbeemmesh_triangles");
- for (i = 0, lt = looptri; i < looptri_num; i++, lt++) {
- tris[(i * 3) + 0] = mloop[lt->tri[0]].v;
- tris[(i * 3) + 1] = mloop[lt->tri[1]].v;
- tris[(i * 3) + 2] = mloop[lt->tri[2]].v;
- }
- *triangles = tris;
-
- BKE_id_free(NULL, mesh);
-}
diff --git a/source/blender/blenkernel/intern/image_save.c b/source/blender/blenkernel/intern/image_save.c
index 4768957e2c8..eba6a1c9174 100644
--- a/source/blender/blenkernel/intern/image_save.c
+++ b/source/blender/blenkernel/intern/image_save.c
@@ -1,6 +1,4 @@
/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -17,13 +15,9 @@
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
- *
- * Contributor(s): Blender Foundation, 2019
- *
- * ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenkernel/intern/image_save.c
+/** \file
* \ingroup bke
*/
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index fd7d2fd4a03..a784be9c645 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -108,7 +108,7 @@ void BKE_modifier_init(void)
const ModifierTypeInfo *modifierType_getInfo(ModifierType type)
{
/* type unsigned, no need to check < 0 */
- if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') {
+ if (type < NUM_MODIFIER_TYPES && modifier_types[type] && modifier_types[type]->name[0] != '\0') {
return modifier_types[type];
}
else {
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 08890965ece..10553e73d8d 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -39,6 +39,7 @@
#include "DNA_key_types.h"
#include "DNA_light_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_material_types.h"
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
@@ -48,7 +49,6 @@
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_shader_fx_types.h"
-#include "DNA_smoke_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
@@ -123,10 +123,6 @@
#include "DRW_engine.h"
-#ifdef WITH_MOD_FLUID
-# include "LBM_fluidsim.h"
-#endif
-
#ifdef WITH_PYTHON
# include "BPY_extern.h"
#endif
@@ -1130,13 +1126,13 @@ void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src, const
}
}
}
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
+ else if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
- if (smd->type == MOD_SMOKE_TYPE_FLOW) {
- if (smd->flow) {
- if (smd->flow->psys == psys) {
- smd->flow->psys = npsys;
+ if (mmd->type == MOD_FLUID_TYPE_FLOW) {
+ if (mmd->flow) {
+ if (mmd->flow->psys == psys) {
+ mmd->flow->psys = npsys;
}
}
}
@@ -4380,10 +4376,10 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
return true;
}
}
- else if (type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
+ else if (type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
- if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) != 0) {
+ if (mmd && (mmd->type & MOD_FLUID_TYPE_DOMAIN) != 0) {
return true;
}
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 096142b9889..ded38cf562f 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -34,7 +34,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_particle_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_scene_types.h"
#include "DNA_dynamicpaint_types.h"
@@ -360,6 +360,11 @@ bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_
}
psmd = psys_get_modifier(ob, psys);
+
+ if (!psmd) {
+ return 0;
+ }
+
if (use_render_params) {
if (!(psmd->modifier.mode & eModifierMode_Render)) {
return 0;
@@ -3577,12 +3582,12 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob
return;
}
- /* clear all other appearances of this pointer (like on smoke flow modifier) */
- if ((md = modifiers_findByType(ob, eModifierType_Smoke))) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type == MOD_SMOKE_TYPE_FLOW) && smd->flow && smd->flow->psys) {
- if (smd->flow->psys == psys) {
- smd->flow->psys = NULL;
+ /* clear all other appearances of this pointer (like on manta flow modifier) */
+ if ((md = modifiers_findByType(ob, eModifierType_Fluid))) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if ((mmd->type == MOD_FLUID_TYPE_FLOW) && mmd->flow && mmd->flow->psys) {
+ if (mmd->flow->psys == psys) {
+ mmd->flow->psys = NULL;
}
}
}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 5985d498606..41ca44fbcd9 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -85,14 +85,11 @@
#include "RE_shader_ext.h"
-/* fluid sim particle import */
-#ifdef WITH_MOD_FLUID
-# include "DNA_object_fluidsim_types.h"
-# include "LBM_fluidsim.h"
-# include <zlib.h>
-# include <string.h>
-
-#endif // WITH_MOD_FLUID
+/* FLUID sim particle import */
+#ifdef WITH_FLUID
+# include "DNA_fluid_types.h"
+# include "manta_fluid_API.h"
+#endif // WITH_FLUID
static ThreadRWMutex psys_bvhtree_rwlock = BLI_RWLOCK_INITIALIZER;
@@ -594,8 +591,6 @@ static void initialize_particle_texture(ParticleSimulationData *sim, ParticleDat
}
pa->time = 0.f;
break;
- case PART_FLUID:
- break;
}
}
@@ -4143,7 +4138,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_
}
static void particles_fluid_step(ParticleSimulationData *sim,
- int UNUSED(cfra),
+ int cfra,
const bool use_render_params)
{
ParticleSystem *psys = sim->psys;
@@ -4153,80 +4148,235 @@ static void particles_fluid_step(ParticleSimulationData *sim,
psys->totpart = 0;
}
- /* fluid sim particle import handling, actual loading of particles from file */
-#ifdef WITH_MOD_FLUID
+#ifdef WITH_FLUID
{
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
- sim->ob, eModifierType_Fluidsim);
+ Object *ob = sim->ob;
+ FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+
+ if (mmd && mmd->domain && mmd->domain->fluid) {
+ FluidDomainSettings *mds = mmd->domain;
- if (fluidmd && fluidmd->fss) {
- FluidsimSettings *fss = fluidmd->fss;
ParticleSettings *part = psys->part;
ParticleData *pa = NULL;
- char filename[256];
- char debugStrBuffer[256];
- int curFrame = sim->scene->r.cfra - 1; // warning - sync with derived mesh fsmesh loading
- int p, j, totpart;
- int readMask, activeParts = 0, fileParts = 0;
- gzFile gzf;
-
- // XXX if (ob==G.obedit) // off...
- // return;
-
- // ok, start loading
- BLI_join_dirfile(
- filename, sizeof(filename), fss->surfdataPath, OB_FLUIDSIM_SURF_PARTICLES_FNAME);
-
- BLI_path_abs(filename, modifier_path_relbase_from_global(sim->ob));
- BLI_path_frame(filename, curFrame, 0); // fixed #frame-no
-
- gzf = BLI_gzopen(filename, "rb");
- if (!gzf) {
+ int p, totpart, tottypepart = 0;
+ int flagActivePart, activeParts = 0;
+ float posX, posY, posZ, velX, velY, velZ;
+ float resX, resY, resZ;
+ int upres = 1;
+ char debugStrBuffer[256];
+ float tmp[3] = {0}, tmp2[3] = {0};
+
+ /* Helper variables for scaling. */
+ float min[3], max[3], size[3], cell_size_scaled[3], max_size;
+
+ /* Sanity check: parts also enabled in fluid domain? */
+ if ((part->type & PART_FLUID_FLIP &&
+ (mds->particle_type & FLUID_DOMAIN_PARTICLE_FLIP) == 0) ||
+ (part->type & PART_FLUID_SPRAY &&
+ (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) == 0) ||
+ (part->type & PART_FLUID_BUBBLE &&
+ (mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) == 0) ||
+ (part->type & PART_FLUID_FOAM &&
+ (mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) == 0) ||
+ (part->type & PART_FLUID_TRACER &&
+ (mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) == 0)) {
BLI_snprintf(debugStrBuffer,
sizeof(debugStrBuffer),
- "readFsPartData::error - Unable to open file for reading '%s'\n",
- filename);
- // XXX bad level call elbeemDebugOut(debugStrBuffer);
+ "particles_fluid_step::error - found particle system that is not enabled in "
+ "fluid domain\n");
+ return;
+ }
+
+ /* Count particle amount. tottypepart is only important for snd particles. */
+ if (part->type & PART_FLUID_FLIP) {
+ tottypepart = totpart = manta_liquid_get_num_flip_particles(mds->fluid);
+ }
+ if (part->type &
+ (PART_FLUID_SPRAY | PART_FLUID_BUBBLE | PART_FLUID_FOAM | PART_FLUID_TRACER)) {
+ totpart = manta_liquid_get_num_snd_particles(mds->fluid);
+
+ /* tottypepart is the amount of particles of a snd particle type. */
+ for (p = 0; p < totpart; p++) {
+ flagActivePart = manta_liquid_get_snd_particle_flag_at(mds->fluid, p);
+ if ((part->type & PART_FLUID_SPRAY) && (flagActivePart & PARTICLE_TYPE_SPRAY)) {
+ tottypepart++;
+ }
+ if ((part->type & PART_FLUID_BUBBLE) && (flagActivePart & PARTICLE_TYPE_BUBBLE)) {
+ tottypepart++;
+ }
+ if ((part->type & PART_FLUID_FOAM) && (flagActivePart & PARTICLE_TYPE_FOAM)) {
+ tottypepart++;
+ }
+ if ((part->type & PART_FLUID_TRACER) && (flagActivePart & PARTICLE_TYPE_TRACER)) {
+ tottypepart++;
+ }
+ }
+ }
+ /* Sanity check: no particles present. */
+ if (!totpart || !tottypepart) {
return;
}
- gzread(gzf, &totpart, sizeof(totpart));
- totpart = (use_render_params) ? totpart : (part->disp * totpart) / 100;
+ /* How many particles to display? */
+ tottypepart = (use_render_params) ? tottypepart : (part->disp * tottypepart) / 100;
- part->totpart = totpart;
+ part->totpart = tottypepart;
part->sta = part->end = 1.0f;
part->lifetime = sim->scene->r.efra + 1;
- /* allocate particles */
+ /* Allocate particles. */
realloc_particles(sim, part->totpart);
- // set up reading mask
- readMask = fss->typeFlags;
+ /* Set some randomness when choosing which particles to display. */
+ sim->rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed);
+ double r, dispProb = (double)part->disp / 100.0;
- for (p = 0, pa = psys->particles; p < totpart; p++, pa++) {
- int ptype = 0;
+ /* Loop over *all* particles. Will break out of loop before tottypepart amount exceeded. */
+ for (p = 0, pa = psys->particles; p < totpart; p++) {
- gzread(gzf, &ptype, sizeof(ptype));
- if (ptype & readMask) {
- activeParts++;
+ /* Apply some randomness and determine which particles to skip. */
+ r = BLI_rng_get_double(sim->rng);
+ if (r > dispProb) {
+ continue;
+ }
- gzread(gzf, &(pa->size), sizeof(float));
+ /* flag, res, upres, pos, vel for FLIP and snd particles have different getters. */
+ if (part->type & PART_FLUID_FLIP) {
+ flagActivePart = manta_liquid_get_flip_particle_flag_at(mds->fluid, p);
- pa->size /= 10.0f;
+ resX = (float)manta_get_res_x(mds->fluid);
+ resY = (float)manta_get_res_y(mds->fluid);
+ resZ = (float)manta_get_res_z(mds->fluid);
- for (j = 0; j < 3; j++) {
- float wrf;
- gzread(gzf, &wrf, sizeof(wrf));
- pa->state.co[j] = wrf;
- // fprintf(stderr,"Rj%d ",j);
- }
- for (j = 0; j < 3; j++) {
- float wrf;
- gzread(gzf, &wrf, sizeof(wrf));
- pa->state.vel[j] = wrf;
+ upres = 1;
+
+ posX = manta_liquid_get_flip_particle_position_x_at(mds->fluid, p);
+ posY = manta_liquid_get_flip_particle_position_y_at(mds->fluid, p);
+ posZ = manta_liquid_get_flip_particle_position_z_at(mds->fluid, p);
+
+ velX = manta_liquid_get_flip_particle_velocity_x_at(mds->fluid, p);
+ velY = manta_liquid_get_flip_particle_velocity_y_at(mds->fluid, p);
+ velZ = manta_liquid_get_flip_particle_velocity_z_at(mds->fluid, p);
+ }
+ else if (part->type &
+ (PART_FLUID_SPRAY | PART_FLUID_BUBBLE | PART_FLUID_FOAM | PART_FLUID_TRACER)) {
+ flagActivePart = manta_liquid_get_snd_particle_flag_at(mds->fluid, p);
+
+ resX = (float)manta_liquid_get_particle_res_x(mds->fluid);
+ resY = (float)manta_liquid_get_particle_res_y(mds->fluid);
+ resZ = (float)manta_liquid_get_particle_res_z(mds->fluid);
+
+ upres = manta_liquid_get_particle_upres(mds->fluid);
+
+ posX = manta_liquid_get_snd_particle_position_x_at(mds->fluid, p);
+ posY = manta_liquid_get_snd_particle_position_y_at(mds->fluid, p);
+ posZ = manta_liquid_get_snd_particle_position_z_at(mds->fluid, p);
+
+ velX = manta_liquid_get_snd_particle_velocity_x_at(mds->fluid, p);
+ velY = manta_liquid_get_snd_particle_velocity_y_at(mds->fluid, p);
+ velZ = manta_liquid_get_snd_particle_velocity_z_at(mds->fluid, p);
+ }
+ else {
+ BLI_snprintf(debugStrBuffer,
+ sizeof(debugStrBuffer),
+ "particles_fluid_step::error - unknown particle system type\n");
+ return;
+ }
+# if 0
+ /* Debugging: Print type of particle system and current particles. */
+ printf("system type is %d and particle type is %d\n", part->type, flagActivePart);
+# endif
+
+ /* Type of particle must match current particle system type
+ * (only important for snd particles). */
+ if ((flagActivePart & PARTICLE_TYPE_SPRAY) && (part->type & PART_FLUID_SPRAY) == 0) {
+ continue;
+ }
+ if ((flagActivePart & PARTICLE_TYPE_BUBBLE) && (part->type & PART_FLUID_BUBBLE) == 0) {
+ continue;
+ }
+ if ((flagActivePart & PARTICLE_TYPE_FOAM) && (part->type & PART_FLUID_FOAM) == 0) {
+ continue;
+ }
+ if ((flagActivePart & PARTICLE_TYPE_TRACER) && (part->type & PART_FLUID_TRACER) == 0) {
+ continue;
+ }
+# if 0
+ /* Debugging: Print type of particle system and current particles. */
+ printf("system type is %d and particle type is %d\n", part->type, flagActivePart);
+# endif
+ /* Particle system has allocated 'tottypepart' particles - so break early before exceeded.
+ */
+ if (activeParts >= tottypepart) {
+ break;
+ }
+
+ /* Only show active particles, i.e. filter out dead particles that just Mantaflow needs.
+ * Mantaflow convention: PARTICLE_TYPE_DELETE == inactive particle. */
+ if ((flagActivePart & PARTICLE_TYPE_DELETE) == 0) {
+ activeParts++;
+
+ /* Use particle system settings for particle size. */
+ pa->size = part->size;
+ if (part->randsize > 0.0f) {
+ pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
}
+ /* Get size (dimension) but considering scaling */
+ copy_v3_v3(cell_size_scaled, mds->cell_size);
+ mul_v3_v3(cell_size_scaled, ob->scale);
+ madd_v3fl_v3fl_v3fl_v3i(min, mds->p0, cell_size_scaled, mds->res_min);
+ madd_v3fl_v3fl_v3fl_v3i(max, mds->p0, cell_size_scaled, mds->res_max);
+ sub_v3_v3v3(size, max, min);
+
+ /* Biggest dimension will be used for up-scaling. */
+ max_size = MAX3(size[0] / (float)upres, size[1] / (float)upres, size[2] / (float)upres);
+
+ /* Set particle position. */
+ float posParticle[3] = {posX, posY, posZ};
+ copy_v3_v3(pa->state.co, posParticle);
+
+ /* Normalize to unit cube around 0. */
+ float resDomain[3] = {resX, resY, resZ};
+ mul_v3_fl(resDomain, 0.5f);
+ sub_v3_v3(pa->state.co, resDomain);
+ mul_v3_fl(pa->state.co, mds->dx);
+
+ /* Match domain dimension / size. */
+ float scaleAbs[3] = {
+ 1. / fabsf(ob->scale[0]), 1. / fabsf(ob->scale[1]), 1. / fabsf(ob->scale[2])};
+ mul_v3_fl(scaleAbs, max_size);
+ mul_v3_v3(pa->state.co, scaleAbs);
+ ;
+
+ /* Match domain scale. */
+ mul_m4_v3(ob->obmat, pa->state.co);
+
+ /* Add origin offset to particle position. */
+ zero_v3(tmp);
+ zero_v3(tmp2);
+ sub_v3_v3v3(tmp2, mds->p1, mds->p0);
+ mul_v3_fl(tmp2, 0.5f);
+ add_v3_v3v3(tmp, tmp, mds->p1);
+ sub_v3_v3(tmp, tmp2);
+ mul_v3_v3(tmp, ob->scale);
+ add_v3_v3(pa->state.co, tmp);
+# if 0
+ /* Debugging: Print particle coordinates. */
+ printf("pa->state.co[0]: %f, pa->state.co[1]: %f, pa->state.co[2]: %f\n",
+ pa->state.co[0], pa->state.co[1], pa->state.co[2]);
+# endif
+ /* Set particle velocity. */
+ float velParticle[3] = {velX, velY, velZ};
+ copy_v3_v3(pa->state.vel, velParticle);
+ mul_v3_fl(pa->state.vel, mds->dx);
+# if 0
+ /* Debugging: Print particle velocity. */
+ printf("pa->state.vel[0]: %f, pa->state.vel[1]: %f, pa->state.vel[2]: %f\n",
+ pa->state.vel[0], pa->state.vel[1], pa->state.vel[2]);
+# endif
+ /* Set default angular velocity and particle rotation. */
zero_v3(pa->state.ave);
unit_qt(pa->state.rot);
@@ -4234,46 +4384,25 @@ static void particles_fluid_step(ParticleSimulationData *sim,
pa->dietime = sim->scene->r.efra + 1;
pa->lifetime = sim->scene->r.efra;
pa->alive = PARS_ALIVE;
-# if 0
- if (a < 25) {
- fprintf(stderr,
- "FSPARTICLE debug set %s, a%d = %f,%f,%f, life=%f\n",
- filename,
- a,
- pa->co[0],
- pa->co[1],
- pa->co[2],
- pa->lifetime);
- }
-# endif
- }
- else {
- // skip...
- for (j = 0; j < 2 * 3 + 1; j++) {
- float wrf;
- gzread(gzf, &wrf, sizeof(wrf));
- }
+
+ /* Increasing particle settings pointer only for active particles. */
+ pa++;
}
- fileParts++;
}
- gzclose(gzf);
+# if 0
+ /* Debugging: Print number of active particles. */
+ printf("active parts: %d\n", activeParts);
+# endif
+ totpart = psys->totpart = part->totpart = activeParts;
- totpart = psys->totpart = activeParts;
- BLI_snprintf(debugStrBuffer,
- sizeof(debugStrBuffer),
- "readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d\n",
- psys->totpart,
- activeParts,
- fileParts,
- readMask);
- // bad level call
- // XXX elbeemDebugOut(debugStrBuffer);
+ BLI_rng_free(sim->rng);
+ sim->rng = NULL;
- } // fluid sim particles done
+ } /* Fluid sim particles done. */
}
#else
UNUSED_VARS(use_render_params);
-#endif // WITH_MOD_FLUID
+#endif // WITH_FLUID
}
static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra))
@@ -4289,12 +4418,16 @@ static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNU
return totpart - oldtotpart;
}
-/* Calculates the next state for all particles of the system
- * In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)
+/**
+ * Calculates the next state for all particles of the system.
+ * In particles code most 'cfra - ending' are frames,
+ * 'time - ending' are 'cfra * timestep' (seconds).
+ *
* 1. Emit particles
* 2. Check cache (if used) and return if frame is cached
* 3. Do dynamics
- * 4. Save to cache */
+ * 4. Save to cache
+ */
static void system_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
{
ParticleSystem *psys = sim->psys;
@@ -4654,128 +4787,124 @@ void particle_system_update(struct Depsgraph *depsgraph,
/* setup necessary physics type dependent additional data if it doesn't yet exist */
psys_prepare_physics(&sim);
- switch (part->type) {
- case PART_HAIR: {
- /* nothing to do so bail out early */
- if (psys->totpart == 0 && part->totpart == 0) {
- psys_free_path_cache(psys, NULL);
- free_hair(ob, psys, 0);
- psys->flag |= PSYS_HAIR_DONE;
- }
- /* (re-)create hair */
- else if (hair_needs_recalc(psys)) {
- float hcfra = 0.0f;
- int i, recalc = psys->recalc;
-
- free_hair(ob, psys, 0);
+ if (part->type & PART_HAIR) {
+ /* nothing to do so bail out early */
+ if (psys->totpart == 0 && part->totpart == 0) {
+ psys_free_path_cache(psys, NULL);
+ free_hair(ob, psys, 0);
+ psys->flag |= PSYS_HAIR_DONE;
+ }
+ /* (re-)create hair */
+ else if (hair_needs_recalc(psys)) {
+ float hcfra = 0.0f;
+ int i, recalc = psys->recalc;
- if (psys_orig->edit && psys_orig->free_edit) {
- psys_orig->free_edit(psys_orig->edit);
- psys_orig->edit = NULL;
- psys_orig->free_edit = NULL;
- }
+ free_hair(ob, psys, 0);
- /* first step is negative so particles get killed and reset */
- psys->cfra = 1.0f;
+ if (psys_orig->edit && psys_orig->free_edit) {
+ psys_orig->free_edit(psys_orig->edit);
+ psys_orig->edit = NULL;
+ psys_orig->free_edit = NULL;
+ }
- ParticleSettings *part_local = part;
- if ((part->flag & PART_HAIR_REGROW) == 0) {
- part_local = particle_settings_localize(part);
- psys->part = part_local;
- }
+ /* first step is negative so particles get killed and reset */
+ psys->cfra = 1.0f;
- for (i = 0; i <= part->hair_step; i++) {
- hcfra = 100.0f * (float)i / (float)psys->part->hair_step;
- if ((part->flag & PART_HAIR_REGROW) == 0) {
- BKE_animsys_evaluate_animdata(
- scene, &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false);
- }
- system_step(&sim, hcfra, use_render_params);
- psys->cfra = hcfra;
- psys->recalc = 0;
- save_hair(&sim, hcfra);
- }
+ ParticleSettings *part_local = part;
+ if ((part->flag & PART_HAIR_REGROW) == 0) {
+ part_local = particle_settings_localize(part);
+ psys->part = part_local;
+ }
- if (part_local != part) {
- particle_settings_free_local(part_local);
- psys->part = part;
+ for (i = 0; i <= part->hair_step; i++) {
+ hcfra = 100.0f * (float)i / (float)psys->part->hair_step;
+ if ((part->flag & PART_HAIR_REGROW) == 0) {
+ BKE_animsys_evaluate_animdata(
+ scene, &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false);
}
-
- psys->flag |= PSYS_HAIR_DONE;
- psys->recalc = recalc;
- }
- else if (psys->flag & PSYS_EDITED) {
- psys->flag |= PSYS_HAIR_DONE;
+ system_step(&sim, hcfra, use_render_params);
+ psys->cfra = hcfra;
+ psys->recalc = 0;
+ save_hair(&sim, hcfra);
}
- if (psys->flag & PSYS_HAIR_DONE) {
- hair_step(&sim, cfra, use_render_params);
+ if (part_local != part) {
+ particle_settings_free_local(part_local);
+ psys->part = part;
}
- break;
+
+ psys->flag |= PSYS_HAIR_DONE;
+ psys->recalc = recalc;
}
- case PART_FLUID: {
- particles_fluid_step(&sim, (int)cfra, use_render_params);
- break;
+ else if (psys->flag & PSYS_EDITED) {
+ psys->flag |= PSYS_HAIR_DONE;
}
- default: {
- switch (part->phystype) {
- case PART_PHYS_NO:
- case PART_PHYS_KEYED: {
- PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys, use_render_params);
- bool free_unexisting = false;
-
- /* Particles without dynamics haven't been reset yet because they don't use pointcache */
- if (psys->recalc & ID_RECALC_PSYS_RESET) {
- psys_reset(psys, PSYS_RESET_ALL);
- }
- if (emit_particles(&sim, NULL, cfra) || (psys->recalc & ID_RECALC_PSYS_RESET)) {
- free_keyed_keys(psys);
- distribute_particles(&sim, part->from);
- initialize_all_particles(&sim);
- free_unexisting = true;
+ if (psys->flag & PSYS_HAIR_DONE) {
+ hair_step(&sim, cfra, use_render_params);
+ }
+ }
+ else if (part->type & (PART_FLUID_FLIP | PART_FLUID_BUBBLE | PART_FLUID_BUBBLE |
+ PART_FLUID_FOAM | PART_FLUID_TRACER)) {
+ particles_fluid_step(&sim, (int)cfra, use_render_params);
+ }
+ else {
+ switch (part->phystype) {
+ case PART_PHYS_NO:
+ case PART_PHYS_KEYED: {
+ PARTICLE_P;
+ float disp = psys_get_current_display_percentage(psys, use_render_params);
+ bool free_unexisting = false;
+
+ /* Particles without dynamics haven't been reset yet because they don't use pointcache */
+ if (psys->recalc & ID_RECALC_PSYS_RESET) {
+ psys_reset(psys, PSYS_RESET_ALL);
+ }
- /* flag for possible explode modifiers after this system */
- sim.psmd->flag |= eParticleSystemFlag_Pars;
- }
+ if (emit_particles(&sim, NULL, cfra) || (psys->recalc & ID_RECALC_PSYS_RESET)) {
+ free_keyed_keys(psys);
+ distribute_particles(&sim, part->from);
+ initialize_all_particles(&sim);
+ free_unexisting = true;
- LOOP_EXISTING_PARTICLES
- {
- pa->size = part->size;
- if (part->randsize > 0.0f) {
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
- }
-
- reset_particle(&sim, pa, 0.0, cfra);
-
- if (psys_frand(psys, p) > disp) {
- pa->flag |= PARS_NO_DISP;
- }
- else {
- pa->flag &= ~PARS_NO_DISP;
- }
- }
+ /* flag for possible explode modifiers after this system */
+ sim.psmd->flag |= eParticleSystemFlag_Pars;
+ }
- /* free unexisting after resetting particles */
- if (free_unexisting) {
- free_unexisting_particles(&sim);
+ LOOP_EXISTING_PARTICLES
+ {
+ pa->size = part->size;
+ if (part->randsize > 0.0f) {
+ pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
}
- if (part->phystype == PART_PHYS_KEYED) {
- psys_count_keyed_targets(&sim);
- set_keyed_keys(&sim);
- psys_update_path_cache(&sim, (int)cfra, use_render_params);
+ reset_particle(&sim, pa, 0.0, cfra);
+
+ if (psys_frand(psys, p) > disp) {
+ pa->flag |= PARS_NO_DISP;
+ }
+ else {
+ pa->flag &= ~PARS_NO_DISP;
}
- break;
}
- default: {
- /* the main dynamic particle system step */
- system_step(&sim, cfra, use_render_params);
- break;
+
+ /* free unexisting after resetting particles */
+ if (free_unexisting) {
+ free_unexisting_particles(&sim);
}
+
+ if (part->phystype == PART_PHYS_KEYED) {
+ psys_count_keyed_targets(&sim);
+ set_keyed_keys(&sim);
+ psys_update_path_cache(&sim, (int)cfra, use_render_params);
+ }
+ break;
+ }
+ default: {
+ /* the main dynamic particle system step */
+ system_step(&sim, cfra, use_render_params);
+ break;
}
- break;
}
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 7ae5f91c615..5e1611cb3f9 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -40,7 +40,7 @@
#include "DNA_particle_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
@@ -64,7 +64,7 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
-#include "BKE_smoke.h"
+#include "BKE_fluid.h"
#include "BKE_softbody.h"
#include "BIK_api.h"
@@ -591,11 +591,11 @@ static void ptcache_cloth_error(void *cloth_v, const char *message)
/* Smoke functions */
static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
+ FluidModifierData *mmd = (FluidModifierData *)smoke_v;
+ FluidDomainSettings *mds = mmd->domain;
- if (sds->fluid) {
- return sds->base_res[0] * sds->base_res[1] * sds->base_res[2];
+ if (mds->fluid) {
+ return mds->base_res[0] * mds->base_res[1] * mds->base_res[2];
}
else {
return 0;
@@ -604,28 +604,28 @@ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
static void ptcache_smoke_error(void *smoke_v, const char *message)
{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
- modifier_setError(&smd->modifier, "%s", message);
+ FluidModifierData *mmd = (FluidModifierData *)smoke_v;
+ modifier_setError(&mmd->modifier, "%s", message);
}
# define SMOKE_CACHE_VERSION "1.04"
static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
+ FluidModifierData *mmd = (FluidModifierData *)smoke_v;
+ FluidDomainSettings *mds = mmd->domain;
int ret = 0;
- int fluid_fields = BKE_smoke_get_data_flags(sds);
+ int fluid_fields = BKE_fluid_get_data_flags(mds);
/* version header */
ptcache_file_write(pf, SMOKE_CACHE_VERSION, 4, sizeof(char));
ptcache_file_write(pf, &fluid_fields, 1, sizeof(int));
- ptcache_file_write(pf, &sds->active_fields, 1, sizeof(int));
- ptcache_file_write(pf, &sds->res, 3, sizeof(int));
- ptcache_file_write(pf, &sds->dx, 1, sizeof(float));
+ ptcache_file_write(pf, &mds->active_fields, 1, sizeof(int));
+ ptcache_file_write(pf, &mds->res, 3, sizeof(int));
+ ptcache_file_write(pf, &mds->dx, 1, sizeof(float));
- if (sds->fluid) {
- size_t res = sds->res[0] * sds->res[1] * sds->res[2];
+ if (mds->fluid) {
+ size_t res = mds->res[0] * mds->res[1] * mds->res[2];
float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
unsigned char *obstacles;
unsigned int in_len = sizeof(float) * (unsigned int)res;
@@ -633,11 +633,11 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
"pointcache_lzo_buffer");
// int mode = res >= 1000000 ? 2 : 1;
int mode = 1; // light
- if (sds->cache_comp == SM_CACHE_HEAVY) {
+ if (mds->cache_comp == SM_CACHE_HEAVY) {
mode = 2; // heavy
}
- smoke_export(sds->fluid,
+ smoke_export(mds->fluid,
&dt,
&dx,
&dens,
@@ -652,20 +652,21 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
&r,
&g,
&b,
- &obstacles);
+ &obstacles,
+ NULL);
- ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
+ ptcache_file_compressed_write(pf, (unsigned char *)mds->shadow, in_len, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode);
- if (fluid_fields & SM_ACTIVE_HEAT) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode);
}
- if (fluid_fields & SM_ACTIVE_FIRE) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)react, in_len, out, mode);
}
- if (fluid_fields & SM_ACTIVE_COLORS) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
ptcache_file_compressed_write(pf, (unsigned char *)r, in_len, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)g, in_len, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)b, in_len, out, mode);
@@ -676,52 +677,52 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
ptcache_file_write(pf, &dt, 1, sizeof(float));
ptcache_file_write(pf, &dx, 1, sizeof(float));
- ptcache_file_write(pf, &sds->p0, 3, sizeof(float));
- ptcache_file_write(pf, &sds->p1, 3, sizeof(float));
- ptcache_file_write(pf, &sds->dp0, 3, sizeof(float));
- ptcache_file_write(pf, &sds->shift, 3, sizeof(int));
- ptcache_file_write(pf, &sds->obj_shift_f, 3, sizeof(float));
- ptcache_file_write(pf, &sds->obmat, 16, sizeof(float));
- ptcache_file_write(pf, &sds->base_res, 3, sizeof(int));
- ptcache_file_write(pf, &sds->res_min, 3, sizeof(int));
- ptcache_file_write(pf, &sds->res_max, 3, sizeof(int));
- ptcache_file_write(pf, &sds->active_color, 3, sizeof(float));
+ ptcache_file_write(pf, &mds->p0, 3, sizeof(float));
+ ptcache_file_write(pf, &mds->p1, 3, sizeof(float));
+ ptcache_file_write(pf, &mds->dp0, 3, sizeof(float));
+ ptcache_file_write(pf, &mds->shift, 3, sizeof(int));
+ ptcache_file_write(pf, &mds->obj_shift_f, 3, sizeof(float));
+ ptcache_file_write(pf, &mds->obmat, 16, sizeof(float));
+ ptcache_file_write(pf, &mds->base_res, 3, sizeof(int));
+ ptcache_file_write(pf, &mds->res_min, 3, sizeof(int));
+ ptcache_file_write(pf, &mds->res_max, 3, sizeof(int));
+ ptcache_file_write(pf, &mds->active_color, 3, sizeof(float));
MEM_freeN(out);
ret = 1;
}
- if (sds->wt) {
+ if (mds->wt) {
int res_big_array[3];
int res_big;
- int res = sds->res[0] * sds->res[1] * sds->res[2];
+ int res = mds->res[0] * mds->res[1] * mds->res[2];
float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
unsigned int in_len = sizeof(float) * (unsigned int)res;
unsigned int in_len_big;
unsigned char *out;
int mode;
- smoke_turbulence_get_res(sds->wt, res_big_array);
+ smoke_turbulence_get_res(mds->wt, res_big_array);
res_big = res_big_array[0] * res_big_array[1] * res_big_array[2];
// mode = res_big >= 1000000 ? 2 : 1;
mode = 1; // light
- if (sds->cache_high_comp == SM_CACHE_HEAVY) {
+ if (mds->cache_high_comp == SM_CACHE_HEAVY) {
mode = 2; // heavy
}
in_len_big = sizeof(float) * (unsigned int)res_big;
- smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
+ smoke_turbulence_export(mds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode);
- if (fluid_fields & SM_ACTIVE_FIRE) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len_big, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len_big, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)react, in_len_big, out, mode);
}
- if (fluid_fields & SM_ACTIVE_COLORS) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
ptcache_file_compressed_write(pf, (unsigned char *)r, in_len_big, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)g, in_len_big, out, mode);
ptcache_file_compressed_write(pf, (unsigned char *)b, in_len_big, out, mode);
@@ -743,24 +744,24 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
/* read old smoke cache from 2.64 */
static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
+ FluidModifierData *mmd = (FluidModifierData *)smoke_v;
+ FluidDomainSettings *mds = mmd->domain;
- if (sds->fluid) {
- const size_t res = sds->res[0] * sds->res[1] * sds->res[2];
+ if (mds->fluid) {
+ const size_t res = mds->res[0] * mds->res[1] * mds->res[2];
const unsigned int out_len = (unsigned int)res * sizeof(float);
float dt, dx, *dens, *heat, *heatold, *vx, *vy, *vz;
unsigned char *obstacles;
float *tmp_array = MEM_callocN(out_len, "Smoke old cache tmp");
- int fluid_fields = BKE_smoke_get_data_flags(sds);
+ int fluid_fields = BKE_fluid_get_data_flags(mds);
/* Part part of the new cache header */
- sds->active_color[0] = 0.7f;
- sds->active_color[1] = 0.7f;
- sds->active_color[2] = 0.7f;
+ mds->active_color[0] = 0.7f;
+ mds->active_color[1] = 0.7f;
+ mds->active_color[2] = 0.7f;
- smoke_export(sds->fluid,
+ smoke_export(mds->fluid,
&dt,
&dx,
&dens,
@@ -775,13 +776,14 @@ static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
NULL,
NULL,
NULL,
- &obstacles);
+ &obstacles,
+ NULL);
- ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char *)mds->shadow, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)tmp_array, out_len);
- if (fluid_fields & SM_ACTIVE_HEAT) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
ptcache_file_compressed_read(pf, (unsigned char *)heat, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)heatold, out_len);
}
@@ -801,19 +803,19 @@ static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
MEM_freeN(tmp_array);
- if (pf->data_types & (1 << BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
+ if (pf->data_types & (1 << BPHYS_DATA_SMOKE_HIGH) && mds->wt) {
int res_big, res_big_array[3];
float *tcu, *tcv, *tcw;
unsigned int out_len_big;
unsigned char *tmp_array_big;
- smoke_turbulence_get_res(sds->wt, res_big_array);
+ smoke_turbulence_get_res(mds->wt, res_big_array);
res_big = res_big_array[0] * res_big_array[1] * res_big_array[2];
out_len_big = sizeof(float) * (unsigned int)res_big;
tmp_array_big = MEM_callocN(out_len_big, "Smoke old cache tmp");
smoke_turbulence_export(
- sds->wt, &dens, NULL, NULL, NULL, NULL, NULL, NULL, &tcu, &tcv, &tcw);
+ mds->wt, &dens, NULL, NULL, NULL, NULL, NULL, NULL, &tcu, &tcv, &tcw);
ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len_big);
ptcache_file_compressed_read(pf, (unsigned char *)tmp_array_big, out_len_big);
@@ -831,12 +833,12 @@ static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
+ FluidModifierData *mmd = (FluidModifierData *)smoke_v;
+ FluidDomainSettings *mds = mmd->domain;
char version[4];
int ch_res[3];
float ch_dx;
- int fluid_fields = BKE_smoke_get_data_flags(sds);
+ int fluid_fields = BKE_fluid_get_data_flags(mds);
int cache_fields = 0;
int active_fields = 0;
int reallocate = 0;
@@ -856,8 +858,8 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
ptcache_file_read(pf, &ch_dx, 1, sizeof(float));
/* check if resolution has changed */
- if (sds->res[0] != ch_res[0] || sds->res[1] != ch_res[1] || sds->res[2] != ch_res[2]) {
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
+ if (mds->res[0] != ch_res[0] || mds->res[1] != ch_res[1] || mds->res[2] != ch_res[2]) {
+ if (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
reallocate = 1;
}
else {
@@ -865,29 +867,26 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
}
}
/* check if active fields have changed */
- if (fluid_fields != cache_fields || active_fields != sds->active_fields) {
+ if (fluid_fields != cache_fields || active_fields != mds->active_fields) {
reallocate = 1;
}
/* reallocate fluid if needed*/
if (reallocate) {
- sds->active_fields = active_fields | cache_fields;
- BKE_smoke_reallocate_fluid(sds, ch_dx, ch_res, 1);
- sds->dx = ch_dx;
- copy_v3_v3_int(sds->res, ch_res);
- sds->total_cells = ch_res[0] * ch_res[1] * ch_res[2];
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- BKE_smoke_reallocate_highres_fluid(sds, ch_dx, ch_res, 1);
- }
+ mds->active_fields = active_fields | cache_fields;
+ BKE_fluid_reallocate_fluid(mds, ch_res, 1);
+ mds->dx = ch_dx;
+ copy_v3_v3_int(mds->res, ch_res);
+ mds->total_cells = ch_res[0] * ch_res[1] * ch_res[2];
}
- if (sds->fluid) {
- size_t res = sds->res[0] * sds->res[1] * sds->res[2];
+ if (mds->fluid) {
+ size_t res = mds->res[0] * mds->res[1] * mds->res[2];
float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
unsigned char *obstacles;
unsigned int out_len = (unsigned int)res * sizeof(float);
- smoke_export(sds->fluid,
+ smoke_export(mds->fluid,
&dt,
&dx,
&dens,
@@ -902,20 +901,21 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
&r,
&g,
&b,
- &obstacles);
+ &obstacles,
+ NULL);
- ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char *)mds->shadow, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len);
- if (cache_fields & SM_ACTIVE_HEAT) {
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
ptcache_file_compressed_read(pf, (unsigned char *)heat, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)heatold, out_len);
}
- if (cache_fields & SM_ACTIVE_FIRE) {
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)react, out_len);
}
- if (cache_fields & SM_ACTIVE_COLORS) {
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
ptcache_file_compressed_read(pf, (unsigned char *)r, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)g, out_len);
ptcache_file_compressed_read(pf, (unsigned char *)b, out_len);
@@ -926,38 +926,38 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
ptcache_file_compressed_read(pf, (unsigned char *)obstacles, (unsigned int)res);
ptcache_file_read(pf, &dt, 1, sizeof(float));
ptcache_file_read(pf, &dx, 1, sizeof(float));
- ptcache_file_read(pf, &sds->p0, 3, sizeof(float));
- ptcache_file_read(pf, &sds->p1, 3, sizeof(float));
- ptcache_file_read(pf, &sds->dp0, 3, sizeof(float));
- ptcache_file_read(pf, &sds->shift, 3, sizeof(int));
- ptcache_file_read(pf, &sds->obj_shift_f, 3, sizeof(float));
- ptcache_file_read(pf, &sds->obmat, 16, sizeof(float));
- ptcache_file_read(pf, &sds->base_res, 3, sizeof(int));
- ptcache_file_read(pf, &sds->res_min, 3, sizeof(int));
- ptcache_file_read(pf, &sds->res_max, 3, sizeof(int));
- ptcache_file_read(pf, &sds->active_color, 3, sizeof(float));
- }
-
- if (pf->data_types & (1 << BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
- int res = sds->res[0] * sds->res[1] * sds->res[2];
+ ptcache_file_read(pf, &mds->p0, 3, sizeof(float));
+ ptcache_file_read(pf, &mds->p1, 3, sizeof(float));
+ ptcache_file_read(pf, &mds->dp0, 3, sizeof(float));
+ ptcache_file_read(pf, &mds->shift, 3, sizeof(int));
+ ptcache_file_read(pf, &mds->obj_shift_f, 3, sizeof(float));
+ ptcache_file_read(pf, &mds->obmat, 16, sizeof(float));
+ ptcache_file_read(pf, &mds->base_res, 3, sizeof(int));
+ ptcache_file_read(pf, &mds->res_min, 3, sizeof(int));
+ ptcache_file_read(pf, &mds->res_max, 3, sizeof(int));
+ ptcache_file_read(pf, &mds->active_color, 3, sizeof(float));
+ }
+
+ if (pf->data_types & (1 << BPHYS_DATA_SMOKE_HIGH) && mds->wt) {
+ int res = mds->res[0] * mds->res[1] * mds->res[2];
int res_big, res_big_array[3];
float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
unsigned int out_len = sizeof(float) * (unsigned int)res;
unsigned int out_len_big;
- smoke_turbulence_get_res(sds->wt, res_big_array);
+ smoke_turbulence_get_res(mds->wt, res_big_array);
res_big = res_big_array[0] * res_big_array[1] * res_big_array[2];
out_len_big = sizeof(float) * (unsigned int)res_big;
- smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
+ smoke_turbulence_export(mds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len_big);
- if (cache_fields & SM_ACTIVE_FIRE) {
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len_big);
ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len_big);
ptcache_file_compressed_read(pf, (unsigned char *)react, out_len_big);
}
- if (cache_fields & SM_ACTIVE_COLORS) {
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
ptcache_file_compressed_read(pf, (unsigned char *)r, out_len_big);
ptcache_file_compressed_read(pf, (unsigned char *)g, out_len_big);
ptcache_file_compressed_read(pf, (unsigned char *)b, out_len_big);
@@ -984,101 +984,101 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
* with `vs` = voxel size, and `px, py, pz`,
* the min position of the domain's bounding box.
*/
-static void compute_fluid_matrices(SmokeDomainSettings *sds)
+static void compute_fluid_matrices(FluidDomainSettings *mds)
{
float bbox_min[3];
- copy_v3_v3(bbox_min, sds->p0);
+ copy_v3_v3(bbox_min, mds->p0);
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
- bbox_min[0] += (sds->cell_size[0] * (float)sds->res_min[0]);
- bbox_min[1] += (sds->cell_size[1] * (float)sds->res_min[1]);
- bbox_min[2] += (sds->cell_size[2] * (float)sds->res_min[2]);
- add_v3_v3(bbox_min, sds->obj_shift_f);
+ if (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
+ bbox_min[0] += (mds->cell_size[0] * (float)mds->res_min[0]);
+ bbox_min[1] += (mds->cell_size[1] * (float)mds->res_min[1]);
+ bbox_min[2] += (mds->cell_size[2] * (float)mds->res_min[2]);
+ add_v3_v3(bbox_min, mds->obj_shift_f);
}
/* construct low res matrix */
- size_to_mat4(sds->fluidmat, sds->cell_size);
- copy_v3_v3(sds->fluidmat[3], bbox_min);
+ size_to_mat4(mds->fluidmat, mds->cell_size);
+ copy_v3_v3(mds->fluidmat[3], bbox_min);
/* The smoke simulator stores voxels cell-centered, whilst VDB is node
* centered, so we offset the matrix by half a voxel to compensate. */
- madd_v3_v3fl(sds->fluidmat[3], sds->cell_size, 0.5f);
+ madd_v3_v3fl(mds->fluidmat[3], mds->cell_size, 0.5f);
- mul_m4_m4m4(sds->fluidmat, sds->obmat, sds->fluidmat);
+ mul_m4_m4m4(mds->fluidmat, mds->obmat, mds->fluidmat);
- if (sds->wt) {
+ if (mds->wt) {
float voxel_size_high[3];
/* construct high res matrix */
- mul_v3_v3fl(voxel_size_high, sds->cell_size, 1.0f / (float)(sds->amplify + 1));
- size_to_mat4(sds->fluidmat_wt, voxel_size_high);
- copy_v3_v3(sds->fluidmat_wt[3], bbox_min);
+ mul_v3_v3fl(voxel_size_high, mds->cell_size, 1.0f / (float)(mds->amplify + 1));
+ size_to_mat4(mds->fluidmat_wt, voxel_size_high);
+ copy_v3_v3(mds->fluidmat_wt[3], bbox_min);
/* Same here, add half a voxel to adjust the position of the fluid. */
- madd_v3_v3fl(sds->fluidmat_wt[3], voxel_size_high, 0.5f);
+ madd_v3_v3fl(mds->fluidmat_wt[3], voxel_size_high, 0.5f);
- mul_m4_m4m4(sds->fluidmat_wt, sds->obmat, sds->fluidmat_wt);
+ mul_m4_m4m4(mds->fluidmat_wt, mds->obmat, mds->fluidmat_wt);
}
}
static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
-
- OpenVDBWriter_set_flags(writer, sds->openvdb_comp, (sds->data_depth == 16));
-
- OpenVDBWriter_add_meta_int(writer, "blender/smoke/active_fields", sds->active_fields);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/resolution", sds->res);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/min_resolution", sds->res_min);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/max_resolution", sds->res_max);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/base_resolution", sds->base_res);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/min_bbox", sds->p0);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/max_bbox", sds->p1);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/dp0", sds->dp0);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/shift", sds->shift);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/obj_shift_f", sds->obj_shift_f);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/active_color", sds->active_color);
- OpenVDBWriter_add_meta_mat4(writer, "blender/smoke/obmat", sds->obmat);
-
- int fluid_fields = BKE_smoke_get_data_flags(sds);
+ FluidModifierData *mmd = (FluidModifierData *)smoke_v;
+ FluidDomainSettings *mds = mmd->domain;
+
+ OpenVDBWriter_set_flags(writer, mds->openvdb_comp, (mds->data_depth == 16));
+
+ OpenVDBWriter_add_meta_int(writer, "blender/smoke/active_fields", mds->active_fields);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/resolution", mds->res);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/min_resolution", mds->res_min);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/max_resolution", mds->res_max);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/base_resolution", mds->base_res);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/min_bbox", mds->p0);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/max_bbox", mds->p1);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/dp0", mds->dp0);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/shift", mds->shift);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/obj_shift_f", mds->obj_shift_f);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/active_color", mds->active_color);
+ OpenVDBWriter_add_meta_mat4(writer, "blender/smoke/obmat", mds->obmat);
+
+ int fluid_fields = BKE_fluid_get_data_flags(mds);
struct OpenVDBFloatGrid *clip_grid = NULL;
- compute_fluid_matrices(sds);
+ compute_fluid_matrices(mds);
OpenVDBWriter_add_meta_int(writer, "blender/smoke/fluid_fields", fluid_fields);
- if (sds->wt) {
+ if (mds->wt) {
struct OpenVDBFloatGrid *wt_density_grid;
float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
- smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
+ smoke_turbulence_export(mds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
wt_density_grid = OpenVDB_export_grid_fl(
- writer, "density", dens, sds->res_wt, sds->fluidmat_wt, sds->clipping, NULL);
+ writer, "density", dens, mds->res_wt, mds->fluidmat_wt, mds->clipping, NULL);
clip_grid = wt_density_grid;
- if (fluid_fields & SM_ACTIVE_FIRE) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
OpenVDB_export_grid_fl(
- writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ writer, "flame", flame, mds->res_wt, mds->fluidmat_wt, mds->clipping, wt_density_grid);
OpenVDB_export_grid_fl(
- writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ writer, "fuel", fuel, mds->res_wt, mds->fluidmat_wt, mds->clipping, wt_density_grid);
OpenVDB_export_grid_fl(
- writer, "react", react, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ writer, "react", react, mds->res_wt, mds->fluidmat_wt, mds->clipping, wt_density_grid);
}
- if (fluid_fields & SM_ACTIVE_COLORS) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
OpenVDB_export_grid_vec(writer,
"color",
r,
g,
b,
- sds->res_wt,
- sds->fluidmat_wt,
+ mds->res_wt,
+ mds->fluidmat_wt,
VEC_INVARIANT,
true,
- sds->clipping,
+ mds->clipping,
wt_density_grid);
}
@@ -1087,20 +1087,20 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
tcu,
tcv,
tcw,
- sds->res,
- sds->fluidmat,
+ mds->res,
+ mds->fluidmat,
VEC_INVARIANT,
false,
- sds->clipping,
+ mds->clipping,
wt_density_grid);
}
- if (sds->fluid) {
+ if (mds->fluid) {
struct OpenVDBFloatGrid *density_grid;
float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
unsigned char *obstacles;
- smoke_export(sds->fluid,
+ smoke_export(mds->fluid,
&dt,
&dx,
&dens,
@@ -1115,50 +1115,51 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
&r,
&g,
&b,
- &obstacles);
+ &obstacles,
+ NULL);
OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx);
OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt);
- const char *name = (!sds->wt) ? "density" : "density_low";
+ const char *name = (!mds->wt) ? "density" : "density_low";
density_grid = OpenVDB_export_grid_fl(
- writer, name, dens, sds->res, sds->fluidmat, sds->clipping, NULL);
- clip_grid = sds->wt ? clip_grid : density_grid;
+ writer, name, dens, mds->res, mds->fluidmat, mds->clipping, NULL);
+ clip_grid = mds->wt ? clip_grid : density_grid;
OpenVDB_export_grid_fl(
- writer, "shadow", sds->shadow, sds->res, sds->fluidmat, sds->clipping, NULL);
+ writer, "shadow", mds->shadow, mds->res, mds->fluidmat, mds->clipping, NULL);
- if (fluid_fields & SM_ACTIVE_HEAT) {
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
OpenVDB_export_grid_fl(
- writer, "heat", heat, sds->res, sds->fluidmat, sds->clipping, clip_grid);
+ writer, "heat", heat, mds->res, mds->fluidmat, mds->clipping, clip_grid);
OpenVDB_export_grid_fl(
- writer, "heat_old", heatold, sds->res, sds->fluidmat, sds->clipping, clip_grid);
+ writer, "heat_old", heatold, mds->res, mds->fluidmat, mds->clipping, clip_grid);
}
- if (fluid_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame_low";
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
+ name = (!mds->wt) ? "flame" : "flame_low";
OpenVDB_export_grid_fl(
- writer, name, flame, sds->res, sds->fluidmat, sds->clipping, density_grid);
- name = (!sds->wt) ? "fuel" : "fuel_low";
+ writer, name, flame, mds->res, mds->fluidmat, mds->clipping, density_grid);
+ name = (!mds->wt) ? "fuel" : "fuel_low";
OpenVDB_export_grid_fl(
- writer, name, fuel, sds->res, sds->fluidmat, sds->clipping, density_grid);
- name = (!sds->wt) ? "react" : "react_low";
+ writer, name, fuel, mds->res, mds->fluidmat, mds->clipping, density_grid);
+ name = (!mds->wt) ? "react" : "react_low";
OpenVDB_export_grid_fl(
- writer, name, react, sds->res, sds->fluidmat, sds->clipping, density_grid);
+ writer, name, react, mds->res, mds->fluidmat, mds->clipping, density_grid);
}
- if (fluid_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color_low";
+ if (fluid_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
+ name = (!mds->wt) ? "color" : "color_low";
OpenVDB_export_grid_vec(writer,
name,
r,
g,
b,
- sds->res,
- sds->fluidmat,
+ mds->res,
+ mds->fluidmat,
VEC_INVARIANT,
true,
- sds->clipping,
+ mds->clipping,
density_grid);
}
@@ -1167,14 +1168,14 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
vx,
vy,
vz,
- sds->res,
- sds->fluidmat,
+ mds->res,
+ mds->fluidmat,
VEC_CONTRAVARIANT_RELATIVE,
false,
- sds->clipping,
+ mds->clipping,
clip_grid);
OpenVDB_export_grid_ch(
- writer, "obstacles", obstacles, sds->res, sds->fluidmat, sds->clipping, NULL);
+ writer, "obstacles", obstacles, mds->res, mds->fluidmat, mds->clipping, NULL);
}
return 1;
@@ -1182,38 +1183,38 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
+ FluidModifierData *mmd = (FluidModifierData *)smoke_v;
- if (!smd) {
+ if (!mmd) {
return 0;
}
- SmokeDomainSettings *sds = smd->domain;
+ FluidDomainSettings *mds = mmd->domain;
- int fluid_fields = BKE_smoke_get_data_flags(sds);
+ int fluid_fields = BKE_fluid_get_data_flags(mds);
int active_fields, cache_fields = 0;
int cache_res[3];
float cache_dx;
bool reallocate = false;
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/min_resolution", sds->res_min);
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/max_resolution", sds->res_max);
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/base_resolution", sds->base_res);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/min_bbox", sds->p0);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/max_bbox", sds->p1);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/dp0", sds->dp0);
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/shift", sds->shift);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/obj_shift_f", sds->obj_shift_f);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/active_color", sds->active_color);
- OpenVDBReader_get_meta_mat4(reader, "blender/smoke/obmat", sds->obmat);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/min_resolution", mds->res_min);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/max_resolution", mds->res_max);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/base_resolution", mds->base_res);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/min_bbox", mds->p0);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/max_bbox", mds->p1);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/dp0", mds->dp0);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/shift", mds->shift);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/obj_shift_f", mds->obj_shift_f);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/active_color", mds->active_color);
+ OpenVDBReader_get_meta_mat4(reader, "blender/smoke/obmat", mds->obmat);
OpenVDBReader_get_meta_int(reader, "blender/smoke/fluid_fields", &cache_fields);
OpenVDBReader_get_meta_int(reader, "blender/smoke/active_fields", &active_fields);
OpenVDBReader_get_meta_fl(reader, "blender/smoke/dx", &cache_dx);
OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/resolution", cache_res);
/* check if resolution has changed */
- if (sds->res[0] != cache_res[0] || sds->res[1] != cache_res[1] || sds->res[2] != cache_res[2]) {
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
+ if (mds->res[0] != cache_res[0] || mds->res[1] != cache_res[1] || mds->res[2] != cache_res[2]) {
+ if (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
reallocate = true;
}
else {
@@ -1222,28 +1223,24 @@ static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_
}
/* check if active fields have changed */
- if ((fluid_fields != cache_fields) || (active_fields != sds->active_fields)) {
+ if ((fluid_fields != cache_fields) || (active_fields != mds->active_fields)) {
reallocate = true;
}
/* reallocate fluid if needed*/
if (reallocate) {
- sds->active_fields = active_fields | cache_fields;
- BKE_smoke_reallocate_fluid(sds, cache_dx, cache_res, 1);
- sds->dx = cache_dx;
- copy_v3_v3_int(sds->res, cache_res);
- sds->total_cells = cache_res[0] * cache_res[1] * cache_res[2];
-
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- BKE_smoke_reallocate_highres_fluid(sds, cache_dx, cache_res, 1);
- }
+ mds->active_fields = active_fields | cache_fields;
+ BKE_fluid_reallocate_fluid(mds, cache_dx, cache_res, 1);
+ mds->dx = cache_dx;
+ copy_v3_v3_int(mds->res, cache_res);
+ mds->total_cells = cache_res[0] * cache_res[1] * cache_res[2];
}
- if (sds->fluid) {
+ if (mds->fluid) {
float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
unsigned char *obstacles;
- smoke_export(sds->fluid,
+ smoke_export(mds->fluid,
&dt,
&dx,
&dens,
@@ -1258,56 +1255,57 @@ static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_
&r,
&g,
&b,
- &obstacles);
+ &obstacles,
+ NULL);
OpenVDBReader_get_meta_fl(reader, "blender/smoke/dt", &dt);
- OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res);
+ OpenVDB_import_grid_fl(reader, "shadow", &mds->shadow, mds->res);
- const char *name = (!sds->wt) ? "density" : "density_low";
- OpenVDB_import_grid_fl(reader, name, &dens, sds->res);
+ const char *name = (!mds->wt) ? "density" : "density_low";
+ OpenVDB_import_grid_fl(reader, name, &dens, mds->res);
- if (cache_fields & SM_ACTIVE_HEAT) {
- OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res);
- OpenVDB_import_grid_fl(reader, "heat_old", &heatold, sds->res);
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
+ OpenVDB_import_grid_fl(reader, "heat", &heat, mds->res);
+ OpenVDB_import_grid_fl(reader, "heat_old", &heatold, mds->res);
}
- if (cache_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame_low";
- OpenVDB_import_grid_fl(reader, name, &flame, sds->res);
- name = (!sds->wt) ? "fuel" : "fuel_low";
- OpenVDB_import_grid_fl(reader, name, &fuel, sds->res);
- name = (!sds->wt) ? "react" : "react_low";
- OpenVDB_import_grid_fl(reader, name, &react, sds->res);
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
+ name = (!mds->wt) ? "flame" : "flame_low";
+ OpenVDB_import_grid_fl(reader, name, &flame, mds->res);
+ name = (!mds->wt) ? "fuel" : "fuel_low";
+ OpenVDB_import_grid_fl(reader, name, &fuel, mds->res);
+ name = (!mds->wt) ? "react" : "react_low";
+ OpenVDB_import_grid_fl(reader, name, &react, mds->res);
}
- if (cache_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color_low";
- OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res);
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
+ name = (!mds->wt) ? "color" : "color_low";
+ OpenVDB_import_grid_vec(reader, name, &r, &g, &b, mds->res);
}
- OpenVDB_import_grid_vec(reader, "velocity", &vx, &vy, &vz, sds->res);
- OpenVDB_import_grid_ch(reader, "obstacles", &obstacles, sds->res);
+ OpenVDB_import_grid_vec(reader, "velocity", &vx, &vy, &vz, mds->res);
+ OpenVDB_import_grid_ch(reader, "obstacles", &obstacles, mds->res);
}
- if (sds->wt) {
+ if (mds->wt) {
float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
- smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
+ smoke_turbulence_export(mds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
- OpenVDB_import_grid_fl(reader, "density", &dens, sds->res_wt);
+ OpenVDB_import_grid_fl(reader, "density", &dens, mds->res_wt);
- if (cache_fields & SM_ACTIVE_FIRE) {
- OpenVDB_import_grid_fl(reader, "flame", &flame, sds->res_wt);
- OpenVDB_import_grid_fl(reader, "fuel", &fuel, sds->res_wt);
- OpenVDB_import_grid_fl(reader, "react", &react, sds->res_wt);
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
+ OpenVDB_import_grid_fl(reader, "flame", &flame, mds->res_wt);
+ OpenVDB_import_grid_fl(reader, "fuel", &fuel, mds->res_wt);
+ OpenVDB_import_grid_fl(reader, "react", &react, mds->res_wt);
}
- if (cache_fields & SM_ACTIVE_COLORS) {
- OpenVDB_import_grid_vec(reader, "color", &r, &g, &b, sds->res_wt);
+ if (cache_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
+ OpenVDB_import_grid_vec(reader, "color", &r, &g, &b, mds->res_wt);
}
- OpenVDB_import_grid_vec(reader, "texture coordinates", &tcu, &tcv, &tcw, sds->res);
+ OpenVDB_import_grid_vec(reader, "texture coordinates", &tcu, &tcv, &tcw, mds->res);
}
OpenVDBReader_free(reader);
@@ -1698,21 +1696,21 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->max_step = 1;
pid->file_type = PTCACHE_FILE_PTCACHE;
}
-void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
+void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct FluidModifierData *mmd)
{
- SmokeDomainSettings *sds = smd->domain;
+ FluidDomainSettings *mds = mmd->domain;
memset(pid, 0, sizeof(PTCacheID));
pid->ob = ob;
- pid->calldata = smd;
+ pid->calldata = mmd;
pid->type = PTCACHE_TYPE_SMOKE_DOMAIN;
- pid->stack_index = sds->point_cache[0]->index;
+ pid->stack_index = mds->point_cache[0]->index;
- pid->cache = sds->point_cache[0];
- pid->cache_ptr = &(sds->point_cache[0]);
- pid->ptcaches = &(sds->ptcaches[0]);
+ pid->cache = mds->point_cache[0];
+ pid->cache_ptr = &(mds->point_cache[0]);
+ pid->ptcaches = &(mds->ptcaches[0]);
pid->totpoint = pid->totwrite = ptcache_smoke_totpoint;
pid->error = ptcache_smoke_error;
@@ -1737,16 +1735,16 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo
pid->data_types = 0;
pid->info_types = 0;
- if (sds->fluid) {
+ if (mds->fluid) {
pid->data_types |= (1 << BPHYS_DATA_SMOKE_LOW);
- }
- if (sds->wt) {
- pid->data_types |= (1 << BPHYS_DATA_SMOKE_HIGH);
+ if (mds->flags & FLUID_DOMAIN_USE_NOISE) {
+ pid->data_types |= (1 << BPHYS_DATA_SMOKE_HIGH);
+ }
}
pid->default_step = 1;
pid->max_step = 1;
- pid->file_type = smd->domain->cache_file_format;
+ pid->file_type = mmd->domain->cache_file_format;
}
void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
@@ -1908,10 +1906,10 @@ static bool foreach_object_modifier_ptcache(Object *object,
return false;
}
}
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- BKE_ptcache_id_from_smoke(&pid, object, (SmokeModifierData *)md);
+ else if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ BKE_ptcache_id_from_smoke(&pid, object, (FluidModifierData *)md);
if (!callback(&pid, callback_user_data)) {
return false;
}
@@ -3741,10 +3739,10 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData *)md);
reset |= BKE_ptcache_id_reset(scene, &pid, mode);
}
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData *)md);
+ if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ BKE_ptcache_id_from_smoke(&pid, ob, (FluidModifierData *)md);
reset |= BKE_ptcache_id_reset(scene, &pid, mode);
}
}
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
deleted file mode 100644
index 4c3b7a619da..00000000000
--- a/source/blender/blenkernel/intern/smoke.c
+++ /dev/null
@@ -1,3654 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup bke
- */
-
-/* Part of the code copied from elbeem fluid library, copyright by Nils Thuerey */
-
-#include "MEM_guardedalloc.h"
-
-#include <float.h>
-#include <math.h>
-#include <stdio.h>
-#include <string.h> /* memset */
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_kdopbvh.h"
-#include "BLI_threads.h"
-#include "BLI_utildefines.h"
-
-#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_customdata_types.h"
-#include "DNA_light_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_smoke_types.h"
-
-#include "BKE_appdir.h"
-#include "BKE_animsys.h"
-#include "BKE_armature.h"
-#include "BKE_bvhutils.h"
-#include "BKE_collision.h"
-#include "BKE_colortools.h"
-#include "BKE_constraint.h"
-#include "BKE_customdata.h"
-#include "BKE_deform.h"
-#include "BKE_effect.h"
-#include "BKE_library.h"
-#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
-#include "BKE_modifier.h"
-#include "BKE_object.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-#include "BKE_scene.h"
-#include "BKE_smoke.h"
-#include "BKE_texture.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
-
-#include "RE_shader_ext.h"
-
-#include "GPU_glew.h"
-
-/* UNUSED so far, may be enabled later */
-/* #define USE_SMOKE_COLLISION_DM */
-
-//#define DEBUG_TIME
-
-#include "smoke_API.h"
-
-#ifdef DEBUG_TIME
-# include "PIL_time.h"
-#endif
-
-#ifdef WITH_SMOKE
-# include "BLI_task.h"
-# include "BLI_kdtree.h"
-# include "BLI_voxel.h"
-
-static ThreadMutex object_update_lock = BLI_MUTEX_INITIALIZER;
-
-struct Mesh;
-struct Object;
-struct Scene;
-struct SmokeModifierData;
-
-// timestep default value for nice appearance 0.1f
-# define DT_DEFAULT 0.1f
-
-# define ADD_IF_LOWER_POS(a, b) (min_ff((a) + (b), max_ff((a), (b))))
-# define ADD_IF_LOWER_NEG(a, b) (max_ff((a) + (b), min_ff((a), (b))))
-# define ADD_IF_LOWER(a, b) (((b) > 0) ? ADD_IF_LOWER_POS((a), (b)) : ADD_IF_LOWER_NEG((a), (b)))
-
-#else /* WITH_SMOKE */
-
-/* Stubs to use when smoke is disabled */
-struct WTURBULENCE *smoke_turbulence_init(int *UNUSED(res),
- int UNUSED(amplify),
- int UNUSED(noisetype),
- const char *UNUSED(noisefile_path),
- int UNUSED(use_fire),
- int UNUSED(use_colors))
-{
- return NULL;
-}
-
-void smoke_free(struct FLUID_3D *UNUSED(fluid))
-{
-}
-float *smoke_get_density(struct FLUID_3D *UNUSED(fluid))
-{
- return NULL;
-}
-void smoke_turbulence_free(struct WTURBULENCE *UNUSED(wt))
-{
-}
-void smoke_initWaveletBlenderRNA(struct WTURBULENCE *UNUSED(wt), float *UNUSED(strength))
-{
-}
-void smoke_initBlenderRNA(struct FLUID_3D *UNUSED(fluid),
- float *UNUSED(alpha),
- float *UNUSED(beta),
- float *UNUSED(dt_factor),
- float *UNUSED(vorticity),
- int *UNUSED(border_colli),
- float *UNUSED(burning_rate),
- float *UNUSED(flame_smoke),
- float *UNUSED(flame_smoke_color),
- float *UNUSED(flame_vorticity),
- float *UNUSED(flame_ignition_temp),
- float *UNUSED(flame_max_temp))
-{
-}
-struct Mesh *smokeModifier_do(SmokeModifierData *UNUSED(smd),
- Depsgraph *UNUSED(depsgraph),
- Scene *UNUSED(scene),
- Object *UNUSED(ob),
- Mesh *UNUSED(me))
-{
- return NULL;
-}
-float BKE_smoke_get_velocity_at(struct Object *UNUSED(ob),
- float UNUSED(position[3]),
- float UNUSED(velocity[3]))
-{
- return 0.0f;
-}
-
-#endif /* WITH_SMOKE */
-
-#ifdef WITH_SMOKE
-
-void BKE_smoke_reallocate_fluid(SmokeDomainSettings *sds, float dx, int res[3], int free_old)
-{
- int use_heat = (sds->active_fields & SM_ACTIVE_HEAT);
- int use_fire = (sds->active_fields & SM_ACTIVE_FIRE);
- int use_colors = (sds->active_fields & SM_ACTIVE_COLORS);
-
- if (free_old && sds->fluid) {
- smoke_free(sds->fluid);
- }
- if (!min_iii(res[0], res[1], res[2])) {
- sds->fluid = NULL;
- return;
- }
- sds->fluid = smoke_init(res, dx, DT_DEFAULT, use_heat, use_fire, use_colors);
- smoke_initBlenderRNA(sds->fluid,
- &(sds->alpha),
- &(sds->beta),
- &(sds->time_scale),
- &(sds->vorticity),
- &(sds->border_collisions),
- &(sds->burning_rate),
- &(sds->flame_smoke),
- sds->flame_smoke_color,
- &(sds->flame_vorticity),
- &(sds->flame_ignition),
- &(sds->flame_max_temp));
-
- /* reallocate shadow buffer */
- if (sds->shadow) {
- MEM_freeN(sds->shadow);
- }
- sds->shadow = MEM_callocN(sizeof(float) * res[0] * res[1] * res[2], "SmokeDomainShadow");
-}
-
-void BKE_smoke_reallocate_highres_fluid(SmokeDomainSettings *sds,
- float dx,
- int res[3],
- int free_old)
-{
- int use_fire = (sds->active_fields & (SM_ACTIVE_HEAT | SM_ACTIVE_FIRE));
- int use_colors = (sds->active_fields & SM_ACTIVE_COLORS);
-
- if (free_old && sds->wt) {
- smoke_turbulence_free(sds->wt);
- }
- if (!min_iii(res[0], res[1], res[2])) {
- sds->wt = NULL;
- return;
- }
-
- /* smoke_turbulence_init uses non-threadsafe functions from fftw3 lib (like fftw_plan & co). */
- BLI_thread_lock(LOCK_FFTW);
-
- sds->wt = smoke_turbulence_init(
- res, sds->amplify + 1, sds->noise, BKE_tempdir_session(), use_fire, use_colors);
-
- BLI_thread_unlock(LOCK_FFTW);
-
- sds->res_wt[0] = res[0] * (sds->amplify + 1);
- sds->res_wt[1] = res[1] * (sds->amplify + 1);
- sds->res_wt[2] = res[2] * (sds->amplify + 1);
- sds->dx_wt = dx / (sds->amplify + 1);
- smoke_initWaveletBlenderRNA(sds->wt, &(sds->strength));
-}
-
-/* convert global position to domain cell space */
-static void smoke_pos_to_cell(SmokeDomainSettings *sds, float pos[3])
-{
- mul_m4_v3(sds->imat, pos);
- sub_v3_v3(pos, sds->p0);
- pos[0] *= 1.0f / sds->cell_size[0];
- pos[1] *= 1.0f / sds->cell_size[1];
- pos[2] *= 1.0f / sds->cell_size[2];
-}
-
-/* set domain transformations and base resolution from object mesh */
-static void smoke_set_domain_from_mesh(SmokeDomainSettings *sds,
- Object *ob,
- Mesh *me,
- bool init_resolution)
-{
- size_t i;
- float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
- float size[3];
- MVert *verts = me->mvert;
- float scale = 0.0;
- int res;
-
- res = sds->maxres;
-
- // get BB of domain
- for (i = 0; i < me->totvert; i++) {
- // min BB
- min[0] = MIN2(min[0], verts[i].co[0]);
- min[1] = MIN2(min[1], verts[i].co[1]);
- min[2] = MIN2(min[2], verts[i].co[2]);
-
- // max BB
- max[0] = MAX2(max[0], verts[i].co[0]);
- max[1] = MAX2(max[1], verts[i].co[1]);
- max[2] = MAX2(max[2], verts[i].co[2]);
- }
-
- /* set domain bounds */
- copy_v3_v3(sds->p0, min);
- copy_v3_v3(sds->p1, max);
- sds->dx = 1.0f / res;
-
- /* calculate domain dimensions */
- sub_v3_v3v3(size, max, min);
- if (init_resolution) {
- zero_v3_int(sds->base_res);
- copy_v3_v3(sds->cell_size, size);
- }
- /* apply object scale */
- for (i = 0; i < 3; i++) {
- size[i] = fabsf(size[i] * ob->scale[i]);
- }
- copy_v3_v3(sds->global_size, size);
- copy_v3_v3(sds->dp0, min);
-
- invert_m4_m4(sds->imat, ob->obmat);
-
- // prevent crash when initializing a plane as domain
- if (!init_resolution || (size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) ||
- (size[2] < FLT_EPSILON)) {
- return;
- }
-
- /* define grid resolutions from longest domain side */
- if (size[0] >= MAX2(size[1], size[2])) {
- scale = res / size[0];
- sds->scale = size[0] / fabsf(ob->scale[0]);
- sds->base_res[0] = res;
- sds->base_res[1] = max_ii((int)(size[1] * scale + 0.5f), 4);
- sds->base_res[2] = max_ii((int)(size[2] * scale + 0.5f), 4);
- }
- else if (size[1] >= MAX2(size[0], size[2])) {
- scale = res / size[1];
- sds->scale = size[1] / fabsf(ob->scale[1]);
- sds->base_res[0] = max_ii((int)(size[0] * scale + 0.5f), 4);
- sds->base_res[1] = res;
- sds->base_res[2] = max_ii((int)(size[2] * scale + 0.5f), 4);
- }
- else {
- scale = res / size[2];
- sds->scale = size[2] / fabsf(ob->scale[2]);
- sds->base_res[0] = max_ii((int)(size[0] * scale + 0.5f), 4);
- sds->base_res[1] = max_ii((int)(size[1] * scale + 0.5f), 4);
- sds->base_res[2] = res;
- }
-
- /* set cell size */
- sds->cell_size[0] /= (float)sds->base_res[0];
- sds->cell_size[1] /= (float)sds->base_res[1];
- sds->cell_size[2] /= (float)sds->base_res[2];
-}
-
-static int smokeModifier_init(SmokeModifierData *smd, Object *ob, int scene_framenr, Mesh *me)
-{
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid) {
- SmokeDomainSettings *sds = smd->domain;
- int res[3];
- /* set domain dimensions from mesh */
- smoke_set_domain_from_mesh(sds, ob, me, true);
- /* reset domain values */
- zero_v3_int(sds->shift);
- zero_v3(sds->shift_f);
- add_v3_fl(sds->shift_f, 0.5f);
- zero_v3(sds->prev_loc);
- mul_m4_v3(ob->obmat, sds->prev_loc);
- copy_m4_m4(sds->obmat, ob->obmat);
-
- /* set resolutions */
- if (smd->domain->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
- res[0] = res[1] = res[2] = 1; /* use minimum res for adaptive init */
- }
- else {
- copy_v3_v3_int(res, sds->base_res);
- }
- copy_v3_v3_int(sds->res, res);
- sds->total_cells = sds->res[0] * sds->res[1] * sds->res[2];
- sds->res_min[0] = sds->res_min[1] = sds->res_min[2] = 0;
- copy_v3_v3_int(sds->res_max, res);
-
- /* allocate fluid */
- BKE_smoke_reallocate_fluid(sds, sds->dx, sds->res, 0);
-
- smd->time = scene_framenr;
-
- /* allocate highres fluid */
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- BKE_smoke_reallocate_highres_fluid(sds, sds->dx, sds->res, 0);
- }
- /* allocate shadow buffer */
- if (!sds->shadow) {
- sds->shadow = MEM_callocN(sizeof(float) * sds->res[0] * sds->res[1] * sds->res[2],
- "SmokeDomainShadow");
- }
- return 1;
- }
- else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
- smd->time = scene_framenr;
-
- return 1;
- }
- else if ((smd->type & MOD_SMOKE_TYPE_COLL)) {
- if (!smd->coll) {
- smokeModifier_createType(smd);
- }
-
- smd->time = scene_framenr;
-
- return 1;
- }
-
- return 2;
-}
-
-#endif /* WITH_SMOKE */
-
-static void smokeModifier_freeDomain(SmokeModifierData *smd)
-{
- if (smd->domain) {
- if (smd->domain->shadow) {
- MEM_freeN(smd->domain->shadow);
- }
- smd->domain->shadow = NULL;
-
- if (smd->domain->fluid) {
- smoke_free(smd->domain->fluid);
- }
-
- if (smd->domain->fluid_mutex) {
- BLI_rw_mutex_free(smd->domain->fluid_mutex);
- }
-
- if (smd->domain->wt) {
- smoke_turbulence_free(smd->domain->wt);
- }
-
- if (smd->domain->effector_weights) {
- MEM_freeN(smd->domain->effector_weights);
- }
- smd->domain->effector_weights = NULL;
-
- if (!(smd->modifier.flag & eModifierFlag_SharedCaches)) {
- BKE_ptcache_free_list(&(smd->domain->ptcaches[0]));
- smd->domain->point_cache[0] = NULL;
- }
-
- if (smd->domain->coba) {
- MEM_freeN(smd->domain->coba);
- }
-
- MEM_freeN(smd->domain);
- smd->domain = NULL;
- }
-}
-
-static void smokeModifier_freeFlow(SmokeModifierData *smd)
-{
- if (smd->flow) {
- if (smd->flow->mesh) {
- BKE_id_free(NULL, smd->flow->mesh);
- }
- if (smd->flow->verts_old) {
- MEM_freeN(smd->flow->verts_old);
- }
- MEM_freeN(smd->flow);
- smd->flow = NULL;
- }
-}
-
-static void smokeModifier_freeCollision(SmokeModifierData *smd)
-{
- if (smd->coll) {
- SmokeCollSettings *scs = smd->coll;
-
- if (scs->numverts) {
- if (scs->verts_old) {
- MEM_freeN(scs->verts_old);
- scs->verts_old = NULL;
- }
- }
-
- if (smd->coll->mesh) {
- BKE_id_free(NULL, smd->coll->mesh);
- }
- smd->coll->mesh = NULL;
-
- MEM_freeN(smd->coll);
- smd->coll = NULL;
- }
-}
-
-void smokeModifier_reset_turbulence(struct SmokeModifierData *smd)
-{
- if (smd && smd->domain && smd->domain->wt) {
- smoke_turbulence_free(smd->domain->wt);
- smd->domain->wt = NULL;
- }
-}
-
-static void smokeModifier_reset_ex(struct SmokeModifierData *smd, bool need_lock)
-{
- if (smd) {
- if (smd->domain) {
- if (smd->domain->shadow) {
- MEM_freeN(smd->domain->shadow);
- }
- smd->domain->shadow = NULL;
-
- if (smd->domain->fluid) {
- if (need_lock) {
- BLI_rw_mutex_lock(smd->domain->fluid_mutex, THREAD_LOCK_WRITE);
- }
-
- smoke_free(smd->domain->fluid);
- smd->domain->fluid = NULL;
-
- if (need_lock) {
- BLI_rw_mutex_unlock(smd->domain->fluid_mutex);
- }
- }
-
- smokeModifier_reset_turbulence(smd);
-
- smd->time = -1;
- smd->domain->total_cells = 0;
- smd->domain->active_fields = 0;
- }
- else if (smd->flow) {
- if (smd->flow->verts_old) {
- MEM_freeN(smd->flow->verts_old);
- }
- smd->flow->verts_old = NULL;
- smd->flow->numverts = 0;
- }
- else if (smd->coll) {
- SmokeCollSettings *scs = smd->coll;
-
- if (scs->numverts && scs->verts_old) {
- MEM_freeN(scs->verts_old);
- scs->verts_old = NULL;
- }
- }
- }
-}
-
-void smokeModifier_reset(struct SmokeModifierData *smd)
-{
- smokeModifier_reset_ex(smd, true);
-}
-
-void smokeModifier_free(SmokeModifierData *smd)
-{
- if (smd) {
- smokeModifier_freeDomain(smd);
- smokeModifier_freeFlow(smd);
- smokeModifier_freeCollision(smd);
- }
-}
-
-void smokeModifier_createType(struct SmokeModifierData *smd)
-{
- if (smd) {
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- if (smd->domain) {
- smokeModifier_freeDomain(smd);
- }
-
- smd->domain = MEM_callocN(sizeof(SmokeDomainSettings), "SmokeDomain");
-
- smd->domain->smd = smd;
-
- smd->domain->point_cache[0] = BKE_ptcache_add(&(smd->domain->ptcaches[0]));
- smd->domain->point_cache[0]->flag |= PTCACHE_DISK_CACHE;
- smd->domain->point_cache[0]->step = 1;
-
- /* Deprecated */
- smd->domain->point_cache[1] = NULL;
- BLI_listbase_clear(&smd->domain->ptcaches[1]);
- /* set some standard values */
- smd->domain->fluid = NULL;
- smd->domain->fluid_mutex = BLI_rw_mutex_alloc();
- smd->domain->wt = NULL;
- smd->domain->eff_group = NULL;
- smd->domain->fluid_group = NULL;
- smd->domain->coll_group = NULL;
- smd->domain->maxres = 32;
- smd->domain->amplify = 1;
- smd->domain->alpha = -0.001;
- smd->domain->beta = 0.1;
- smd->domain->time_scale = 1.0;
- smd->domain->vorticity = 2.0;
- smd->domain->border_collisions = SM_BORDER_OPEN; // open domain
- smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG;
- smd->domain->highres_sampling = SM_HRES_FULLSAMPLE;
- smd->domain->strength = 2.0;
- smd->domain->noise = MOD_SMOKE_NOISEWAVE;
- smd->domain->diss_speed = 5;
- smd->domain->active_fields = 0;
-
- smd->domain->adapt_margin = 4;
- smd->domain->adapt_res = 0;
- smd->domain->adapt_threshold = 0.02f;
-
- smd->domain->burning_rate = 0.75f;
- smd->domain->flame_smoke = 1.0f;
- smd->domain->flame_vorticity = 0.5f;
- smd->domain->flame_ignition = 1.5f;
- smd->domain->flame_max_temp = 3.0f;
- /* color */
- smd->domain->flame_smoke_color[0] = 0.7f;
- smd->domain->flame_smoke_color[1] = 0.7f;
- smd->domain->flame_smoke_color[2] = 0.7f;
-
- smd->domain->viewsettings = MOD_SMOKE_VIEW_SHOW_HIGHRES;
- smd->domain->effector_weights = BKE_effector_add_weights(NULL);
-
-#ifdef WITH_OPENVDB_BLOSC
- smd->domain->openvdb_comp = VDB_COMPRESSION_BLOSC;
-#else
- smd->domain->openvdb_comp = VDB_COMPRESSION_ZIP;
-#endif
- smd->domain->data_depth = 0;
- smd->domain->cache_file_format = PTCACHE_FILE_PTCACHE;
-
- smd->domain->display_thickness = 1.0f;
- smd->domain->slice_method = MOD_SMOKE_SLICE_VIEW_ALIGNED;
- smd->domain->axis_slice_method = AXIS_SLICE_FULL;
- smd->domain->slice_per_voxel = 5.0f;
- smd->domain->slice_depth = 0.5f;
- smd->domain->slice_axis = 0;
- smd->domain->vector_scale = 1.0f;
-
- smd->domain->coba = NULL;
- smd->domain->coba_field = FLUID_FIELD_DENSITY;
-
- smd->domain->clipping = 1e-3f;
- }
- else if (smd->type & MOD_SMOKE_TYPE_FLOW) {
- if (smd->flow) {
- smokeModifier_freeFlow(smd);
- }
-
- smd->flow = MEM_callocN(sizeof(SmokeFlowSettings), "SmokeFlow");
-
- smd->flow->smd = smd;
-
- /* set some standard values */
- smd->flow->density = 1.0f;
- smd->flow->fuel_amount = 1.0f;
- smd->flow->temp = 1.0f;
- smd->flow->flags = MOD_SMOKE_FLOW_ABSOLUTE | MOD_SMOKE_FLOW_USE_PART_SIZE;
- smd->flow->vel_multi = 1.0f;
- smd->flow->volume_density = 0.0f;
- smd->flow->surface_distance = 1.5f;
- smd->flow->source = MOD_SMOKE_FLOW_SOURCE_MESH;
- smd->flow->texture_size = 1.0f;
- smd->flow->particle_size = 1.0f;
- smd->flow->subframes = 0;
-
- smd->flow->color[0] = 0.7f;
- smd->flow->color[1] = 0.7f;
- smd->flow->color[2] = 0.7f;
-
- smd->flow->mesh = NULL;
- smd->flow->psys = NULL;
- }
- else if (smd->type & MOD_SMOKE_TYPE_COLL) {
- if (smd->coll) {
- smokeModifier_freeCollision(smd);
- }
-
- smd->coll = MEM_callocN(sizeof(SmokeCollSettings), "SmokeColl");
-
- smd->coll->smd = smd;
- smd->coll->verts_old = NULL;
- smd->coll->numverts = 0;
- smd->coll->type = 0; // static obstacle
- smd->coll->mesh = NULL;
- }
- }
-}
-
-void smokeModifier_copy(const struct SmokeModifierData *smd,
- struct SmokeModifierData *tsmd,
- const int flag)
-{
- tsmd->type = smd->type;
- tsmd->time = smd->time;
-
- smokeModifier_createType(tsmd);
-
- if (tsmd->domain) {
- SmokeDomainSettings *tsds = tsmd->domain;
- SmokeDomainSettings *sds = smd->domain;
-
- BKE_ptcache_free_list(&(tsds->ptcaches[0]));
-
- if (flag & LIB_ID_CREATE_NO_MAIN) {
- /* Share the cache with the original object's modifier. */
- tsmd->modifier.flag |= eModifierFlag_SharedCaches;
- tsds->point_cache[0] = sds->point_cache[0];
- tsds->ptcaches[0] = sds->ptcaches[0];
- }
- else {
- tsds->point_cache[0] = BKE_ptcache_copy_list(
- &(tsds->ptcaches[0]), &(sds->ptcaches[0]), flag);
- }
-
- tsds->fluid_group = sds->fluid_group;
- tsds->coll_group = sds->coll_group;
-
- tsds->adapt_margin = sds->adapt_margin;
- tsds->adapt_res = sds->adapt_res;
- tsds->adapt_threshold = sds->adapt_threshold;
-
- tsds->alpha = sds->alpha;
- tsds->beta = sds->beta;
- tsds->amplify = sds->amplify;
- tsds->maxres = sds->maxres;
- tsds->flags = sds->flags;
- tsds->highres_sampling = sds->highres_sampling;
- tsds->viewsettings = sds->viewsettings;
- tsds->noise = sds->noise;
- tsds->diss_speed = sds->diss_speed;
- tsds->strength = sds->strength;
-
- tsds->border_collisions = sds->border_collisions;
- tsds->vorticity = sds->vorticity;
- tsds->time_scale = sds->time_scale;
-
- tsds->burning_rate = sds->burning_rate;
- tsds->flame_smoke = sds->flame_smoke;
- tsds->flame_vorticity = sds->flame_vorticity;
- tsds->flame_ignition = sds->flame_ignition;
- tsds->flame_max_temp = sds->flame_max_temp;
- copy_v3_v3(tsds->flame_smoke_color, sds->flame_smoke_color);
-
- MEM_freeN(tsds->effector_weights);
- tsds->effector_weights = MEM_dupallocN(sds->effector_weights);
- tsds->openvdb_comp = sds->openvdb_comp;
- tsds->data_depth = sds->data_depth;
- tsds->cache_file_format = sds->cache_file_format;
-
- tsds->display_thickness = sds->display_thickness;
- tsds->slice_method = sds->slice_method;
- tsds->axis_slice_method = sds->axis_slice_method;
- tsds->slice_per_voxel = sds->slice_per_voxel;
- tsds->slice_depth = sds->slice_depth;
- tsds->slice_axis = sds->slice_axis;
- tsds->interp_method = sds->interp_method;
- tsds->draw_velocity = sds->draw_velocity;
- tsds->vector_draw_type = sds->vector_draw_type;
- tsds->vector_scale = sds->vector_scale;
-
- tsds->use_coba = sds->use_coba;
- tsds->coba_field = sds->coba_field;
- if (sds->coba) {
- tsds->coba = MEM_dupallocN(sds->coba);
- }
-
- tsds->clipping = sds->clipping;
- }
- else if (tsmd->flow) {
- SmokeFlowSettings *tsfs = tsmd->flow;
- SmokeFlowSettings *sfs = smd->flow;
-
- tsfs->psys = sfs->psys;
- tsfs->noise_texture = sfs->noise_texture;
-
- tsfs->vel_multi = sfs->vel_multi;
- tsfs->vel_normal = sfs->vel_normal;
- tsfs->vel_random = sfs->vel_random;
-
- tsfs->density = sfs->density;
- copy_v3_v3(tsfs->color, sfs->color);
- tsfs->fuel_amount = sfs->fuel_amount;
- tsfs->temp = sfs->temp;
- tsfs->volume_density = sfs->volume_density;
- tsfs->surface_distance = sfs->surface_distance;
- tsfs->particle_size = sfs->particle_size;
- tsfs->subframes = sfs->subframes;
-
- tsfs->texture_size = sfs->texture_size;
- tsfs->texture_offset = sfs->texture_offset;
- BLI_strncpy(tsfs->uvlayer_name, sfs->uvlayer_name, sizeof(tsfs->uvlayer_name));
- tsfs->vgroup_density = sfs->vgroup_density;
-
- tsfs->type = sfs->type;
- tsfs->source = sfs->source;
- tsfs->texture_type = sfs->texture_type;
- tsfs->flags = sfs->flags;
- }
- else if (tsmd->coll) {
- /* leave it as initialized, collision settings is mostly caches */
- }
-}
-
-#ifdef WITH_SMOKE
-
-// forward declaration
-static void smoke_calc_transparency(SmokeDomainSettings *sds, ViewLayer *view_layer);
-static float calc_voxel_transp(
- float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
-
-static int get_light(ViewLayer *view_layer, float *light)
-{
- Base *base_tmp = NULL;
- int found_light = 0;
-
- // try to find a lamp, preferably local
- for (base_tmp = FIRSTBASE(view_layer); base_tmp; base_tmp = base_tmp->next) {
- if (base_tmp->object->type == OB_LAMP) {
- Light *la = base_tmp->object->data;
-
- if (la->type == LA_LOCAL) {
- copy_v3_v3(light, base_tmp->object->obmat[3]);
- return 1;
- }
- else if (!found_light) {
- copy_v3_v3(light, base_tmp->object->obmat[3]);
- found_light = 1;
- }
- }
- }
-
- return found_light;
-}
-
-/**********************************************************
- * Obstacles
- **********************************************************/
-
-typedef struct ObstaclesFromDMData {
- SmokeDomainSettings *sds;
- const MVert *mvert;
- const MLoop *mloop;
- const MLoopTri *looptri;
- BVHTreeFromMesh *tree;
- unsigned char *obstacle_map;
-
- bool has_velocity;
- float *vert_vel;
- float *velocityX, *velocityY, *velocityZ;
- int *num_obstacles;
-} ObstaclesFromDMData;
-
-static void obstacles_from_mesh_task_cb(void *__restrict userdata,
- const int z,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- ObstaclesFromDMData *data = userdata;
- SmokeDomainSettings *sds = data->sds;
-
- /* slightly rounded-up sqrt(3 * (0.5)^2) == max. distance of cell boundary along the diagonal */
- const float surface_distance = 0.867f;
-
- for (int x = sds->res_min[0]; x < sds->res_max[0]; x++) {
- for (int y = sds->res_min[1]; y < sds->res_max[1]; y++) {
- const int index = smoke_get_index(
- x - sds->res_min[0], sds->res[0], y - sds->res_min[1], sds->res[1], z - sds->res_min[2]);
-
- float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f};
- BVHTreeNearest nearest = {0};
- nearest.index = -1;
- nearest.dist_sq = surface_distance *
- surface_distance; /* find_nearest uses squared distance */
-
- /* find the nearest point on the mesh */
- if (BLI_bvhtree_find_nearest(
- data->tree->tree, ray_start, &nearest, data->tree->nearest_callback, data->tree) !=
- -1) {
- const MLoopTri *lt = &data->looptri[nearest.index];
- float weights[3];
- int v1, v2, v3;
-
- /* calculate barycentric weights for nearest point */
- v1 = data->mloop[lt->tri[0]].v;
- v2 = data->mloop[lt->tri[1]].v;
- v3 = data->mloop[lt->tri[2]].v;
- interp_weights_tri_v3(
- weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, nearest.co);
-
- // DG TODO
- if (data->has_velocity) {
- /* apply object velocity */
- {
- float hit_vel[3];
- interp_v3_v3v3v3(hit_vel,
- &data->vert_vel[v1 * 3],
- &data->vert_vel[v2 * 3],
- &data->vert_vel[v3 * 3],
- weights);
- data->velocityX[index] += hit_vel[0];
- data->velocityY[index] += hit_vel[1];
- data->velocityZ[index] += hit_vel[2];
- }
- }
-
- /* tag obstacle cells */
- data->obstacle_map[index] = 1;
-
- if (data->has_velocity) {
- data->obstacle_map[index] |= 8;
- data->num_obstacles[index]++;
- }
- }
- }
- }
-}
-
-static void obstacles_from_mesh(Object *coll_ob,
- SmokeDomainSettings *sds,
- SmokeCollSettings *scs,
- unsigned char *obstacle_map,
- float *velocityX,
- float *velocityY,
- float *velocityZ,
- int *num_obstacles,
- float dt)
-{
- if (!scs->mesh) {
- return;
- }
- {
- Mesh *me = NULL;
- MVert *mvert = NULL;
- const MLoopTri *looptri;
- const MLoop *mloop;
- BVHTreeFromMesh treeData = {NULL};
- int numverts, i;
-
- float *vert_vel = NULL;
- bool has_velocity = false;
-
- me = BKE_mesh_copy_for_eval(scs->mesh, true);
- BKE_mesh_ensure_normals(me);
- mvert = me->mvert;
- mloop = me->mloop;
- looptri = BKE_mesh_runtime_looptri_ensure(me);
- numverts = me->totvert;
-
- // DG TODO
- // if (scs->type > SM_COLL_STATIC)
- // if line above is used, the code is in trouble if the object moves
- // but is declared as "does not move".
-
- {
- vert_vel = MEM_callocN(sizeof(float) * numverts * 3, "smoke_obs_velocity");
-
- if (scs->numverts != numverts || !scs->verts_old) {
- if (scs->verts_old) {
- MEM_freeN(scs->verts_old);
- }
-
- scs->verts_old = MEM_callocN(sizeof(float) * numverts * 3, "smoke_obs_verts_old");
- scs->numverts = numverts;
- }
- else {
- has_velocity = true;
- }
- }
-
- /* Transform collider vertices to
- * domain grid space for fast lookups */
- for (i = 0; i < numverts; i++) {
- float n[3];
- float co[3];
-
- /* vert pos */
- mul_m4_v3(coll_ob->obmat, mvert[i].co);
- smoke_pos_to_cell(sds, mvert[i].co);
-
- /* vert normal */
- normal_short_to_float_v3(n, mvert[i].no);
- mul_mat3_m4_v3(coll_ob->obmat, n);
- mul_mat3_m4_v3(sds->imat, n);
- normalize_v3(n);
- normal_float_to_short_v3(mvert[i].no, n);
-
- /* vert velocity */
- add_v3fl_v3fl_v3i(co, mvert[i].co, sds->shift);
- if (has_velocity) {
- sub_v3_v3v3(&vert_vel[i * 3], co, &scs->verts_old[i * 3]);
- mul_v3_fl(&vert_vel[i * 3], sds->dx / dt);
- }
- copy_v3_v3(&scs->verts_old[i * 3], co);
- }
-
- if (BKE_bvhtree_from_mesh_get(&treeData, me, BVHTREE_FROM_LOOPTRI, 4)) {
- ObstaclesFromDMData data = {
- .sds = sds,
- .mvert = mvert,
- .mloop = mloop,
- .looptri = looptri,
- .tree = &treeData,
- .obstacle_map = obstacle_map,
- .has_velocity = has_velocity,
- .vert_vel = vert_vel,
- .velocityX = velocityX,
- .velocityY = velocityY,
- .velocityZ = velocityZ,
- .num_obstacles = num_obstacles,
- };
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
- BLI_task_parallel_range(
- sds->res_min[2], sds->res_max[2], &data, obstacles_from_mesh_task_cb, &settings);
- }
- /* free bvh tree */
- free_bvhtree_from_mesh(&treeData);
- BKE_id_free(NULL, me);
-
- if (vert_vel) {
- MEM_freeN(vert_vel);
- }
- }
-}
-
-/* Animated obstacles: dx_step = ((x_new - x_old) / totalsteps) * substep */
-static void update_obstacles(Depsgraph *depsgraph,
- Object *ob,
- SmokeDomainSettings *sds,
- float dt,
- int UNUSED(substep),
- int UNUSED(totalsteps))
-{
- Object **collobjs = NULL;
- unsigned int numcollobj = 0;
-
- unsigned int collIndex;
- unsigned char *obstacles = smoke_get_obstacle(sds->fluid);
- float *velx = NULL;
- float *vely = NULL;
- float *velz = NULL;
- float *velxOrig = smoke_get_velocity_x(sds->fluid);
- float *velyOrig = smoke_get_velocity_y(sds->fluid);
- float *velzOrig = smoke_get_velocity_z(sds->fluid);
- float *density = smoke_get_density(sds->fluid);
- float *fuel = smoke_get_fuel(sds->fluid);
- float *flame = smoke_get_flame(sds->fluid);
- float *r = smoke_get_color_r(sds->fluid);
- float *g = smoke_get_color_g(sds->fluid);
- float *b = smoke_get_color_b(sds->fluid);
- unsigned int z;
-
- int *num_obstacles = MEM_callocN(sizeof(int) * sds->res[0] * sds->res[1] * sds->res[2],
- "smoke_num_obstacles");
-
- smoke_get_ob_velocity(sds->fluid, &velx, &vely, &velz);
-
- // TODO: delete old obstacle flags
- for (z = 0; z < sds->res[0] * sds->res[1] * sds->res[2]; z++) {
- if (obstacles[z] & 8) // Do not delete static obstacles
- {
- obstacles[z] = 0;
- }
-
- velx[z] = 0;
- vely[z] = 0;
- velz[z] = 0;
- }
-
- collobjs = BKE_collision_objects_create(
- depsgraph, ob, sds->coll_group, &numcollobj, eModifierType_Smoke);
-
- // update obstacle tags in cells
- for (collIndex = 0; collIndex < numcollobj; collIndex++) {
- Object *collob = collobjs[collIndex];
- SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(collob,
- eModifierType_Smoke);
-
- // DG TODO: check if modifier is active?
-
- if ((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) {
- SmokeCollSettings *scs = smd2->coll;
- obstacles_from_mesh(collob, sds, scs, obstacles, velx, vely, velz, num_obstacles, dt);
- }
- }
-
- BKE_collision_objects_free(collobjs);
-
- /* obstacle cells should not contain any velocity from the smoke simulation */
- for (z = 0; z < sds->res[0] * sds->res[1] * sds->res[2]; z++) {
- if (obstacles[z]) {
- velxOrig[z] = 0;
- velyOrig[z] = 0;
- velzOrig[z] = 0;
- density[z] = 0;
- if (fuel) {
- fuel[z] = 0;
- flame[z] = 0;
- }
- if (r) {
- r[z] = 0;
- g[z] = 0;
- b[z] = 0;
- }
- }
- /* average velocities from multiple obstacles in one cell */
- if (num_obstacles[z]) {
- velx[z] /= num_obstacles[z];
- vely[z] /= num_obstacles[z];
- velz[z] /= num_obstacles[z];
- }
- }
-
- MEM_freeN(num_obstacles);
-}
-
-/**********************************************************
- * Flow emission code
- **********************************************************/
-
-typedef struct EmissionMap {
- float *influence;
- float *influence_high;
- float *velocity;
- int min[3], max[3], res[3];
- int hmin[3], hmax[3], hres[3];
- int total_cells, valid;
-} EmissionMap;
-
-static void em_boundInsert(EmissionMap *em, float point[3])
-{
- int i = 0;
- if (!em->valid) {
- for (; i < 3; i++) {
- em->min[i] = (int)floor(point[i]);
- em->max[i] = (int)ceil(point[i]);
- }
- em->valid = 1;
- }
- else {
- for (; i < 3; i++) {
- if (point[i] < em->min[i]) {
- em->min[i] = (int)floor(point[i]);
- }
- if (point[i] > em->max[i]) {
- em->max[i] = (int)ceil(point[i]);
- }
- }
- }
-}
-
-static void clampBoundsInDomain(SmokeDomainSettings *sds,
- int min[3],
- int max[3],
- float *min_vel,
- float *max_vel,
- int margin,
- float dt)
-{
- int i;
- for (i = 0; i < 3; i++) {
- int adapt = (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) ? sds->adapt_res : 0;
- /* add margin */
- min[i] -= margin;
- max[i] += margin;
-
- /* adapt to velocity */
- if (min_vel && min_vel[i] < 0.0f) {
- min[i] += (int)floor(min_vel[i] * dt);
- }
- if (max_vel && max_vel[i] > 0.0f) {
- max[i] += (int)ceil(max_vel[i] * dt);
- }
-
- /* clamp within domain max size */
- CLAMP(min[i], -adapt, sds->base_res[i] + adapt);
- CLAMP(max[i], -adapt, sds->base_res[i] + adapt);
- }
-}
-
-static void em_allocateData(EmissionMap *em, bool use_velocity, int hires_mul)
-{
- int i, res[3];
-
- for (i = 0; i < 3; i++) {
- res[i] = em->max[i] - em->min[i];
- if (res[i] <= 0) {
- return;
- }
- }
- em->total_cells = res[0] * res[1] * res[2];
- copy_v3_v3_int(em->res, res);
-
- em->influence = MEM_callocN(sizeof(float) * em->total_cells, "smoke_flow_influence");
- if (use_velocity) {
- em->velocity = MEM_callocN(sizeof(float) * em->total_cells * 3, "smoke_flow_velocity");
- }
-
- /* allocate high resolution map if required */
- if (hires_mul > 1) {
- int total_cells_high = em->total_cells * (hires_mul * hires_mul * hires_mul);
-
- for (i = 0; i < 3; i++) {
- em->hmin[i] = em->min[i] * hires_mul;
- em->hmax[i] = em->max[i] * hires_mul;
- em->hres[i] = em->res[i] * hires_mul;
- }
-
- em->influence_high = MEM_callocN(sizeof(float) * total_cells_high,
- "smoke_flow_influence_high");
- }
- em->valid = 1;
-}
-
-static void em_freeData(EmissionMap *em)
-{
- if (em->influence) {
- MEM_freeN(em->influence);
- }
- if (em->influence_high) {
- MEM_freeN(em->influence_high);
- }
- if (em->velocity) {
- MEM_freeN(em->velocity);
- }
-}
-
-static void em_combineMaps(
- EmissionMap *output, EmissionMap *em2, int hires_multiplier, int additive, float sample_size)
-{
- int i, x, y, z;
-
- /* copyfill input 1 struct and clear output for new allocation */
- EmissionMap em1;
- memcpy(&em1, output, sizeof(EmissionMap));
- memset(output, 0, sizeof(EmissionMap));
-
- for (i = 0; i < 3; i++) {
- if (em1.valid) {
- output->min[i] = MIN2(em1.min[i], em2->min[i]);
- output->max[i] = MAX2(em1.max[i], em2->max[i]);
- }
- else {
- output->min[i] = em2->min[i];
- output->max[i] = em2->max[i];
- }
- }
- /* allocate output map */
- em_allocateData(output, (em1.velocity || em2->velocity), hires_multiplier);
-
- /* base resolution inputs */
- for (x = output->min[0]; x < output->max[0]; x++) {
- for (y = output->min[1]; y < output->max[1]; y++) {
- for (z = output->min[2]; z < output->max[2]; z++) {
- int index_out = smoke_get_index(x - output->min[0],
- output->res[0],
- y - output->min[1],
- output->res[1],
- z - output->min[2]);
-
- /* initialize with first input if in range */
- if (x >= em1.min[0] && x < em1.max[0] && y >= em1.min[1] && y < em1.max[1] &&
- z >= em1.min[2] && z < em1.max[2]) {
- int index_in = smoke_get_index(
- x - em1.min[0], em1.res[0], y - em1.min[1], em1.res[1], z - em1.min[2]);
-
- /* values */
- output->influence[index_out] = em1.influence[index_in];
- if (output->velocity && em1.velocity) {
- copy_v3_v3(&output->velocity[index_out * 3], &em1.velocity[index_in * 3]);
- }
- }
-
- /* apply second input if in range */
- if (x >= em2->min[0] && x < em2->max[0] && y >= em2->min[1] && y < em2->max[1] &&
- z >= em2->min[2] && z < em2->max[2]) {
- int index_in = smoke_get_index(
- x - em2->min[0], em2->res[0], y - em2->min[1], em2->res[1], z - em2->min[2]);
-
- /* values */
- if (additive) {
- output->influence[index_out] += em2->influence[index_in] * sample_size;
- }
- else {
- output->influence[index_out] = MAX2(em2->influence[index_in],
- output->influence[index_out]);
- }
- if (output->velocity && em2->velocity) {
- /* last sample replaces the velocity */
- output->velocity[index_out * 3] = ADD_IF_LOWER(output->velocity[index_out * 3],
- em2->velocity[index_in * 3]);
- output->velocity[index_out * 3 + 1] = ADD_IF_LOWER(output->velocity[index_out * 3 + 1],
- em2->velocity[index_in * 3 + 1]);
- output->velocity[index_out * 3 + 2] = ADD_IF_LOWER(output->velocity[index_out * 3 + 2],
- em2->velocity[index_in * 3 + 2]);
- }
- }
- } // low res loop
- }
- }
-
- /* initialize high resolution input if available */
- if (output->influence_high) {
- for (x = output->hmin[0]; x < output->hmax[0]; x++) {
- for (y = output->hmin[1]; y < output->hmax[1]; y++) {
- for (z = output->hmin[2]; z < output->hmax[2]; z++) {
- int index_out = smoke_get_index(x - output->hmin[0],
- output->hres[0],
- y - output->hmin[1],
- output->hres[1],
- z - output->hmin[2]);
-
- /* initialize with first input if in range */
- if (x >= em1.hmin[0] && x < em1.hmax[0] && y >= em1.hmin[1] && y < em1.hmax[1] &&
- z >= em1.hmin[2] && z < em1.hmax[2]) {
- int index_in = smoke_get_index(
- x - em1.hmin[0], em1.hres[0], y - em1.hmin[1], em1.hres[1], z - em1.hmin[2]);
- /* values */
- output->influence_high[index_out] = em1.influence_high[index_in];
- }
-
- /* apply second input if in range */
- if (x >= em2->hmin[0] && x < em2->hmax[0] && y >= em2->hmin[1] && y < em2->hmax[1] &&
- z >= em2->hmin[2] && z < em2->hmax[2]) {
- int index_in = smoke_get_index(
- x - em2->hmin[0], em2->hres[0], y - em2->hmin[1], em2->hres[1], z - em2->hmin[2]);
-
- /* values */
- if (additive) {
- output->influence_high[index_out] += em2->influence_high[index_in] * sample_size;
- }
- else {
- output->influence_high[index_out] = MAX2(em2->influence_high[index_in],
- output->influence_high[index_out]);
- }
- }
- } // high res loop
- }
- }
- }
-
- /* free original data */
- em_freeData(&em1);
-}
-
-typedef struct EmitFromParticlesData {
- SmokeFlowSettings *sfs;
- KDTree_3d *tree;
- int hires_multiplier;
-
- EmissionMap *em;
- float *particle_vel;
- float hr;
-
- int *min, *max, *res;
-
- float solid;
- float smooth;
- float hr_smooth;
-} EmitFromParticlesData;
-
-static void emit_from_particles_task_cb(void *__restrict userdata,
- const int z,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- EmitFromParticlesData *data = userdata;
- SmokeFlowSettings *sfs = data->sfs;
- EmissionMap *em = data->em;
- const int hires_multiplier = data->hires_multiplier;
-
- for (int x = data->min[0]; x < data->max[0]; x++) {
- for (int y = data->min[1]; y < data->max[1]; y++) {
- /* take low res samples where possible */
- if (hires_multiplier <= 1 ||
- !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
- /* get low res space coordinates */
- const int lx = x / hires_multiplier;
- const int ly = y / hires_multiplier;
- const int lz = z / hires_multiplier;
-
- const int index = smoke_get_index(
- lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
- const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
-
- /* find particle distance from the kdtree */
- KDTreeNearest_3d nearest;
- const float range = data->solid + data->smooth;
- BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
-
- if (nearest.dist < range) {
- em->influence[index] = (nearest.dist < data->solid) ?
- 1.0f :
- (1.0f - (nearest.dist - data->solid) / data->smooth);
- /* Uses particle velocity as initial velocity for smoke */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY &&
- (sfs->psys->part->phystype != PART_PHYS_NO)) {
- madd_v3_v3fl(
- &em->velocity[index * 3], &data->particle_vel[nearest.index * 3], sfs->vel_multi);
- }
- }
- }
-
- /* take high res samples if required */
- if (hires_multiplier > 1) {
- /* get low res space coordinates */
- const float lx = ((float)x) * data->hr;
- const float ly = ((float)y) * data->hr;
- const float lz = ((float)z) * data->hr;
-
- const int index = smoke_get_index(
- x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
- const float ray_start[3] = {
- lx + 0.5f * data->hr, ly + 0.5f * data->hr, lz + 0.5f * data->hr};
-
- /* find particle distance from the kdtree */
- KDTreeNearest_3d nearest;
- const float range = data->solid + data->hr_smooth;
- BLI_kdtree_3d_find_nearest(data->tree, ray_start, &nearest);
-
- if (nearest.dist < range) {
- em->influence_high[index] = (nearest.dist < data->solid) ?
- 1.0f :
- (1.0f - (nearest.dist - data->solid) / data->smooth);
- }
- }
- }
- }
-}
-
-static void emit_from_particles(Object *flow_ob,
- SmokeDomainSettings *sds,
- SmokeFlowSettings *sfs,
- EmissionMap *em,
- Depsgraph *depsgraph,
- Scene *scene,
- float dt)
-{
- /* Is particle system selected. */
- if (sfs && sfs->psys && sfs->psys->part &&
- ELEM(sfs->psys->part->type, PART_EMITTER, PART_FLUID)) {
- ParticleSimulationData sim;
- ParticleSystem *psys = sfs->psys;
- float *particle_pos;
- float *particle_vel;
- int totpart = psys->totpart, totchild;
- int p = 0;
- int valid_particles = 0;
- int bounds_margin = 1;
-
- /* radius based flow */
- const float solid = sfs->particle_size * 0.5f;
- const float smooth = 0.5f; /* add 0.5 cells of linear falloff to reduce aliasing */
- int hires_multiplier = 1;
- KDTree_3d *tree = NULL;
-
- sim.depsgraph = depsgraph;
- sim.scene = scene;
- sim.ob = flow_ob;
- sim.psys = psys;
- sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- /* prepare curvemapping tables */
- if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve) {
- BKE_curvemapping_changed_all(psys->part->clumpcurve);
- }
- if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) {
- BKE_curvemapping_changed_all(psys->part->roughcurve);
- }
- if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve) {
- BKE_curvemapping_changed_all(psys->part->twistcurve);
- }
-
- /* initialize particle cache */
- if (psys->part->type == PART_HAIR) {
- // TODO: PART_HAIR not supported whatsoever
- totchild = 0;
- }
- else {
- totchild = psys->totchild * psys->part->disp / 100;
- }
-
- particle_pos = MEM_callocN(sizeof(float) * (totpart + totchild) * 3, "smoke_flow_particles");
- particle_vel = MEM_callocN(sizeof(float) * (totpart + totchild) * 3, "smoke_flow_particles");
-
- /* setup particle radius emission if enabled */
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- tree = BLI_kdtree_3d_new(psys->totpart + psys->totchild);
-
- /* check need for high resolution map */
- if ((sds->flags & MOD_SMOKE_HIGHRES) && (sds->highres_sampling == SM_HRES_FULLSAMPLE)) {
- hires_multiplier = sds->amplify + 1;
- }
-
- bounds_margin = (int)ceil(solid + smooth);
- }
-
- /* calculate local position for each particle */
- for (p = 0; p < totpart + totchild; p++) {
- ParticleKey state;
- float *pos;
- if (p < totpart) {
- if (psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
- continue;
- }
- }
- else {
- /* handle child particle */
- ChildParticle *cpa = &psys->child[p - totpart];
- if (psys->particles[cpa->parent].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
- continue;
- }
- }
-
- /* DEG_get_ctime(depsgraph) does not give subframe time */
- state.time = BKE_scene_frame_get(scene);
- if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
- continue;
- }
-
- /* location */
- pos = &particle_pos[valid_particles * 3];
- copy_v3_v3(pos, state.co);
- smoke_pos_to_cell(sds, pos);
-
- /* velocity */
- copy_v3_v3(&particle_vel[valid_particles * 3], state.vel);
- mul_mat3_m4_v3(sds->imat, &particle_vel[valid_particles * 3]);
-
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- BLI_kdtree_3d_insert(tree, valid_particles, pos);
- }
-
- /* calculate emission map bounds */
- em_boundInsert(em, pos);
- valid_particles++;
- }
-
- /* set emission map */
- clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, bounds_margin, dt);
- em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY, hires_multiplier);
-
- if (!(sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE)) {
- for (p = 0; p < valid_particles; p++) {
- int cell[3];
- size_t i = 0;
- size_t index = 0;
- int badcell = 0;
-
- /* 1. get corresponding cell */
- cell[0] = floor(particle_pos[p * 3]) - em->min[0];
- cell[1] = floor(particle_pos[p * 3 + 1]) - em->min[1];
- cell[2] = floor(particle_pos[p * 3 + 2]) - em->min[2];
- /* check if cell is valid (in the domain boundary) */
- for (i = 0; i < 3; i++) {
- if ((cell[i] > em->res[i] - 1) || (cell[i] < 0)) {
- badcell = 1;
- break;
- }
- }
- if (badcell) {
- continue;
- }
- /* get cell index */
- index = smoke_get_index(cell[0], em->res[0], cell[1], em->res[1], cell[2]);
- /* Add influence to emission map */
- em->influence[index] = 1.0f;
- /* Uses particle velocity as initial velocity for smoke */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO)) {
- madd_v3_v3fl(&em->velocity[index * 3], &particle_vel[p * 3], sfs->vel_multi);
- }
- } // particles loop
- }
- else if (valid_particles > 0) { // MOD_SMOKE_FLOW_USE_PART_SIZE
- int min[3], max[3], res[3];
- const float hr = 1.0f / ((float)hires_multiplier);
- /* slightly adjust high res antialias smoothness based on number of divisions
- * to allow smaller details but yet not differing too much from the low res size */
- const float hr_smooth = smooth * powf(hr, 1.0f / 3.0f);
-
- /* setup loop bounds */
- for (int i = 0; i < 3; i++) {
- min[i] = em->min[i] * hires_multiplier;
- max[i] = em->max[i] * hires_multiplier;
- res[i] = em->res[i] * hires_multiplier;
- }
-
- BLI_kdtree_3d_balance(tree);
-
- EmitFromParticlesData data = {
- .sfs = sfs,
- .tree = tree,
- .hires_multiplier = hires_multiplier,
- .hr = hr,
- .em = em,
- .particle_vel = particle_vel,
- .min = min,
- .max = max,
- .res = res,
- .solid = solid,
- .smooth = smooth,
- .hr_smooth = hr_smooth,
- };
-
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
- BLI_task_parallel_range(min[2], max[2], &data, emit_from_particles_task_cb, &settings);
- }
-
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- BLI_kdtree_3d_free(tree);
- }
-
- /* free data */
- if (particle_pos) {
- MEM_freeN(particle_pos);
- }
- if (particle_vel) {
- MEM_freeN(particle_vel);
- }
- }
-}
-
-static void sample_mesh(SmokeFlowSettings *sfs,
- const MVert *mvert,
- const MLoop *mloop,
- const MLoopTri *mlooptri,
- const MLoopUV *mloopuv,
- float *influence_map,
- float *velocity_map,
- int index,
- const int base_res[3],
- float flow_center[3],
- BVHTreeFromMesh *treeData,
- const float ray_start[3],
- const float *vert_vel,
- bool has_velocity,
- int defgrp_index,
- MDeformVert *dvert,
- float x,
- float y,
- float z)
-{
- float ray_dir[3] = {1.0f, 0.0f, 0.0f};
- BVHTreeRayHit hit = {0};
- BVHTreeNearest nearest = {0};
-
- float volume_factor = 0.0f;
- float sample_str = 0.0f;
-
- hit.index = -1;
- hit.dist = 9999;
- nearest.index = -1;
- nearest.dist_sq = sfs->surface_distance *
- sfs->surface_distance; /* find_nearest uses squared distance */
-
- /* Check volume collision */
- if (sfs->volume_density) {
- if (BLI_bvhtree_ray_cast(treeData->tree,
- ray_start,
- ray_dir,
- 0.0f,
- &hit,
- treeData->raycast_callback,
- treeData) != -1) {
- float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2];
- /* If ray and hit face normal are facing same direction
- * hit point is inside a closed mesh. */
- if (dot >= 0) {
- /* Also cast a ray in opposite direction to make sure
- * point is at least surrounded by two faces */
- negate_v3(ray_dir);
- hit.index = -1;
- hit.dist = 9999;
-
- BLI_bvhtree_ray_cast(
- treeData->tree, ray_start, ray_dir, 0.0f, &hit, treeData->raycast_callback, treeData);
- if (hit.index != -1) {
- volume_factor = sfs->volume_density;
- }
- }
- }
- }
-
- /* find the nearest point on the mesh */
- if (BLI_bvhtree_find_nearest(
- treeData->tree, ray_start, &nearest, treeData->nearest_callback, treeData) != -1) {
- float weights[3];
- int v1, v2, v3, f_index = nearest.index;
- float n1[3], n2[3], n3[3], hit_normal[3];
-
- /* emit from surface based on distance */
- if (sfs->surface_distance) {
- sample_str = sqrtf(nearest.dist_sq) / sfs->surface_distance;
- CLAMP(sample_str, 0.0f, 1.0f);
- sample_str = pow(1.0f - sample_str, 0.5f);
- }
- else {
- sample_str = 0.0f;
- }
-
- /* calculate barycentric weights for nearest point */
- v1 = mloop[mlooptri[f_index].tri[0]].v;
- v2 = mloop[mlooptri[f_index].tri[1]].v;
- v3 = mloop[mlooptri[f_index].tri[2]].v;
- interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
-
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
- /* apply normal directional velocity */
- if (sfs->vel_normal) {
- /* interpolate vertex normal vectors to get nearest point normal */
- normal_short_to_float_v3(n1, mvert[v1].no);
- normal_short_to_float_v3(n2, mvert[v2].no);
- normal_short_to_float_v3(n3, mvert[v3].no);
- interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights);
- normalize_v3(hit_normal);
- /* apply normal directional and random velocity
- * - TODO: random disabled for now since it doesn't really work well
- * as pressure calc smoothens it out. */
- velocity_map[index * 3] += hit_normal[0] * sfs->vel_normal * 0.25f;
- velocity_map[index * 3 + 1] += hit_normal[1] * sfs->vel_normal * 0.25f;
- velocity_map[index * 3 + 2] += hit_normal[2] * sfs->vel_normal * 0.25f;
- /* TODO: for fire emitted from mesh surface we can use
- * Vf = Vs + (Ps/Pf - 1)*S to model gaseous expansion from solid to fuel */
- }
- /* apply object velocity */
- if (has_velocity && sfs->vel_multi) {
- float hit_vel[3];
- interp_v3_v3v3v3(
- hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights);
- velocity_map[index * 3] += hit_vel[0] * sfs->vel_multi;
- velocity_map[index * 3 + 1] += hit_vel[1] * sfs->vel_multi;
- velocity_map[index * 3 + 2] += hit_vel[2] * sfs->vel_multi;
- }
- }
-
- /* apply vertex group influence if used */
- if (defgrp_index != -1 && dvert) {
- float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] +
- defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] +
- defvert_find_weight(&dvert[v3], defgrp_index) * weights[2];
- sample_str *= weight_mask;
- }
-
- /* apply emission texture */
- if ((sfs->flags & MOD_SMOKE_FLOW_TEXTUREEMIT) && sfs->noise_texture) {
- float tex_co[3] = {0};
- TexResult texres;
-
- if (sfs->texture_type == MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO) {
- tex_co[0] = ((x - flow_center[0]) / base_res[0]) / sfs->texture_size;
- tex_co[1] = ((y - flow_center[1]) / base_res[1]) / sfs->texture_size;
- tex_co[2] = ((z - flow_center[2]) / base_res[2] - sfs->texture_offset) / sfs->texture_size;
- }
- else if (mloopuv) {
- const float *uv[3];
- uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
- uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
- uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
-
- interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
-
- /* map between -1.0f and 1.0f */
- tex_co[0] = tex_co[0] * 2.0f - 1.0f;
- tex_co[1] = tex_co[1] * 2.0f - 1.0f;
- tex_co[2] = sfs->texture_offset;
- }
- texres.nor = NULL;
- BKE_texture_get_value(NULL, sfs->noise_texture, tex_co, &texres, false);
- sample_str *= texres.tin;
- }
- }
-
- /* multiply initial velocity by emitter influence */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
- mul_v3_fl(&velocity_map[index * 3], sample_str);
- }
-
- /* apply final influence based on volume factor */
- influence_map[index] = MAX2(volume_factor, sample_str);
-}
-
-typedef struct EmitFromDMData {
- SmokeDomainSettings *sds;
- SmokeFlowSettings *sfs;
- const MVert *mvert;
- const MLoop *mloop;
- const MLoopTri *mlooptri;
- const MLoopUV *mloopuv;
- MDeformVert *dvert;
- int defgrp_index;
-
- BVHTreeFromMesh *tree;
- int hires_multiplier;
- float hr;
-
- EmissionMap *em;
- bool has_velocity;
- float *vert_vel;
-
- float *flow_center;
- int *min, *max, *res;
-} EmitFromDMData;
-
-static void emit_from_mesh_task_cb(void *__restrict userdata,
- const int z,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- EmitFromDMData *data = userdata;
- EmissionMap *em = data->em;
- const int hires_multiplier = data->hires_multiplier;
-
- for (int x = data->min[0]; x < data->max[0]; x++) {
- for (int y = data->min[1]; y < data->max[1]; y++) {
- /* take low res samples where possible */
- if (hires_multiplier <= 1 ||
- !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
- /* get low res space coordinates */
- const int lx = x / hires_multiplier;
- const int ly = y / hires_multiplier;
- const int lz = z / hires_multiplier;
-
- const int index = smoke_get_index(
- lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
- const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
-
- sample_mesh(data->sfs,
- data->mvert,
- data->mloop,
- data->mlooptri,
- data->mloopuv,
- em->influence,
- em->velocity,
- index,
- data->sds->base_res,
- data->flow_center,
- data->tree,
- ray_start,
- data->vert_vel,
- data->has_velocity,
- data->defgrp_index,
- data->dvert,
- (float)lx,
- (float)ly,
- (float)lz);
- }
-
- /* take high res samples if required */
- if (hires_multiplier > 1) {
- /* get low res space coordinates */
- const float lx = ((float)x) * data->hr;
- const float ly = ((float)y) * data->hr;
- const float lz = ((float)z) * data->hr;
-
- const int index = smoke_get_index(
- x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
- const float ray_start[3] = {
- lx + 0.5f * data->hr,
- ly + 0.5f * data->hr,
- lz + 0.5f * data->hr,
- };
-
- sample_mesh(data->sfs,
- data->mvert,
- data->mloop,
- data->mlooptri,
- data->mloopuv,
- em->influence_high,
- NULL,
- index,
- data->sds->base_res,
- data->flow_center,
- data->tree,
- ray_start,
- data->vert_vel,
- data->has_velocity,
- data->defgrp_index,
- data->dvert,
- /* x,y,z needs to be always lowres */
- lx,
- ly,
- lz);
- }
- }
- }
-}
-
-static void emit_from_mesh(
- Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, float dt)
-{
- if (sfs->mesh) {
- Mesh *me;
- int defgrp_index = sfs->vgroup_density - 1;
- MDeformVert *dvert = NULL;
- MVert *mvert = NULL;
- const MLoopTri *mlooptri = NULL;
- const MLoopUV *mloopuv = NULL;
- const MLoop *mloop = NULL;
- BVHTreeFromMesh treeData = {NULL};
- int numOfVerts, i;
- float flow_center[3] = {0};
-
- float *vert_vel = NULL;
- int has_velocity = 0;
- int min[3], max[3], res[3];
- int hires_multiplier = 1;
-
- /* copy mesh for thread safety because we modify it,
- * main issue is its VertArray being modified, then replaced and freed
- */
- me = BKE_mesh_copy_for_eval(sfs->mesh, true);
-
- /* Duplicate vertices to modify. */
- if (me->mvert) {
- me->mvert = MEM_dupallocN(me->mvert);
- CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert);
- }
-
- BKE_mesh_ensure_normals(me);
- mvert = me->mvert;
- numOfVerts = me->totvert;
- dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
- mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, sfs->uvlayer_name);
- mloop = me->mloop;
- mlooptri = BKE_mesh_runtime_looptri_ensure(me);
-
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) {
- vert_vel = MEM_callocN(sizeof(float) * numOfVerts * 3, "smoke_flow_velocity");
-
- if (sfs->numverts != numOfVerts || !sfs->verts_old) {
- if (sfs->verts_old) {
- MEM_freeN(sfs->verts_old);
- }
- sfs->verts_old = MEM_callocN(sizeof(float) * numOfVerts * 3, "smoke_flow_verts_old");
- sfs->numverts = numOfVerts;
- }
- else {
- has_velocity = 1;
- }
- }
-
- /* Transform mesh vertices to
- * domain grid space for fast lookups */
- for (i = 0; i < numOfVerts; i++) {
- float n[3];
- /* vert pos */
- mul_m4_v3(flow_ob->obmat, mvert[i].co);
- smoke_pos_to_cell(sds, mvert[i].co);
- /* vert normal */
- normal_short_to_float_v3(n, mvert[i].no);
- mul_mat3_m4_v3(flow_ob->obmat, n);
- mul_mat3_m4_v3(sds->imat, n);
- normalize_v3(n);
- normal_float_to_short_v3(mvert[i].no, n);
- /* vert velocity */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) {
- float co[3];
- add_v3fl_v3fl_v3i(co, mvert[i].co, sds->shift);
- if (has_velocity) {
- sub_v3_v3v3(&vert_vel[i * 3], co, &sfs->verts_old[i * 3]);
- mul_v3_fl(&vert_vel[i * 3], sds->dx / dt);
- }
- copy_v3_v3(&sfs->verts_old[i * 3], co);
- }
-
- /* calculate emission map bounds */
- em_boundInsert(em, mvert[i].co);
- }
- mul_m4_v3(flow_ob->obmat, flow_center);
- smoke_pos_to_cell(sds, flow_center);
-
- /* check need for high resolution map */
- if ((sds->flags & MOD_SMOKE_HIGHRES) && (sds->highres_sampling == SM_HRES_FULLSAMPLE)) {
- hires_multiplier = sds->amplify + 1;
- }
-
- /* set emission map */
- clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, (int)ceil(sfs->surface_distance), dt);
- em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY, hires_multiplier);
-
- /* setup loop bounds */
- for (i = 0; i < 3; i++) {
- min[i] = em->min[i] * hires_multiplier;
- max[i] = em->max[i] * hires_multiplier;
- res[i] = em->res[i] * hires_multiplier;
- }
-
- if (BKE_bvhtree_from_mesh_get(&treeData, me, BVHTREE_FROM_LOOPTRI, 4)) {
- const float hr = 1.0f / ((float)hires_multiplier);
-
- EmitFromDMData data = {
- .sds = sds,
- .sfs = sfs,
- .mvert = mvert,
- .mloop = mloop,
- .mlooptri = mlooptri,
- .mloopuv = mloopuv,
- .dvert = dvert,
- .defgrp_index = defgrp_index,
- .tree = &treeData,
- .hires_multiplier = hires_multiplier,
- .hr = hr,
- .em = em,
- .has_velocity = has_velocity,
- .vert_vel = vert_vel,
- .flow_center = flow_center,
- .min = min,
- .max = max,
- .res = res,
- };
-
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
- BLI_task_parallel_range(min[2], max[2], &data, emit_from_mesh_task_cb, &settings);
- }
- /* free bvh tree */
- free_bvhtree_from_mesh(&treeData);
-
- if (vert_vel) {
- MEM_freeN(vert_vel);
- }
-
- if (me->mvert) {
- MEM_freeN(me->mvert);
- }
- BKE_id_free(NULL, me);
- }
-}
-
-/**********************************************************
- * Smoke step
- **********************************************************/
-
-static void adjustDomainResolution(SmokeDomainSettings *sds,
- int new_shift[3],
- EmissionMap *emaps,
- unsigned int numflowobj,
- float dt)
-{
- const int block_size = sds->amplify + 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];
- int x, y, z;
- float *density = smoke_get_density(sds->fluid);
- float *fuel = smoke_get_fuel(sds->fluid);
- float *bigdensity = smoke_turbulence_get_density(sds->wt);
- float *bigfuel = smoke_turbulence_get_fuel(sds->wt);
- float *vx = smoke_get_velocity_x(sds->fluid);
- float *vy = smoke_get_velocity_y(sds->fluid);
- float *vz = smoke_get_velocity_z(sds->fluid);
- int wt_res[3];
-
- if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
- smoke_turbulence_get_res(sds->wt, wt_res);
- }
-
- INIT_MINMAX(min_vel, max_vel);
-
- /* Calculate bounds for current domain content */
- for (x = sds->res_min[0]; x < sds->res_max[0]; x++) {
- for (y = sds->res_min[1]; y < sds->res_max[1]; y++) {
- for (z = sds->res_min[2]; z < sds->res_max[2]; z++) {
- int xn = x - new_shift[0];
- int yn = y - new_shift[1];
- int zn = z - new_shift[2];
- int index;
- float max_den;
-
- /* skip if cell already belongs to new area */
- if (xn >= min[0] && xn <= max[0] && yn >= min[1] && yn <= max[1] && zn >= min[2] &&
- zn <= max[2]) {
- continue;
- }
-
- index = smoke_get_index(x - sds->res_min[0],
- sds->res[0],
- y - sds->res_min[1],
- sds->res[1],
- z - sds->res_min[2]);
- max_den = (fuel) ? MAX2(density[index], fuel[index]) : density[index];
-
- /* check high resolution bounds if max density isnt already high enough */
- if (max_den < sds->adapt_threshold && sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
- int i, j, k;
- /* high res grid index */
- int xx = (x - sds->res_min[0]) * block_size;
- int yy = (y - sds->res_min[1]) * block_size;
- int zz = (z - sds->res_min[2]) * block_size;
-
- for (i = 0; i < block_size; i++) {
- for (j = 0; j < block_size; j++) {
- for (k = 0; k < block_size; k++) {
- int big_index = smoke_get_index(xx + i, wt_res[0], yy + j, wt_res[1], zz + k);
- float den = (bigfuel) ? MAX2(bigdensity[big_index], bigfuel[big_index]) :
- bigdensity[big_index];
- if (den > max_den) {
- max_den = den;
- }
- }
- }
- }
- }
-
- /* content bounds (use shifted coordinates) */
- if (max_den >= sds->adapt_threshold) {
- if (min[0] > xn) {
- min[0] = xn;
- }
- if (min[1] > yn) {
- min[1] = yn;
- }
- if (min[2] > zn) {
- min[2] = zn;
- }
- if (max[0] < xn) {
- max[0] = xn;
- }
- if (max[1] < yn) {
- max[1] = yn;
- }
- if (max[2] < zn) {
- max[2] = zn;
- }
- }
-
- /* velocity bounds */
- if (min_vel[0] > vx[index]) {
- min_vel[0] = vx[index];
- }
- if (min_vel[1] > vy[index]) {
- min_vel[1] = vy[index];
- }
- if (min_vel[2] > vz[index]) {
- min_vel[2] = vz[index];
- }
- if (max_vel[0] < vx[index]) {
- max_vel[0] = vx[index];
- }
- if (max_vel[1] < vy[index]) {
- max_vel[1] = vy[index];
- }
- if (max_vel[2] < vz[index]) {
- max_vel[2] = vz[index];
- }
- }
- }
- }
-
- /* also apply emission maps */
- for (int i = 0; i < numflowobj; i++) {
- EmissionMap *em = &emaps[i];
-
- for (x = em->min[0]; x < em->max[0]; x++) {
- for (y = em->min[1]; y < em->max[1]; y++) {
- for (z = em->min[2]; z < em->max[2]; z++) {
- int index = smoke_get_index(
- x - em->min[0], em->res[0], y - em->min[1], em->res[1], z - em->min[2]);
- float max_den = em->influence[index];
-
- /* density bounds */
- if (max_den >= sds->adapt_threshold) {
- if (min[0] > x) {
- min[0] = x;
- }
- if (min[1] > y) {
- min[1] = y;
- }
- if (min[2] > z) {
- min[2] = z;
- }
- if (max[0] < x) {
- max[0] = x;
- }
- if (max[1] < y) {
- max[1] = y;
- }
- if (max[2] < z) {
- max[2] = z;
- }
- }
- }
- }
- }
- }
-
- /* calculate new bounds based on these values */
- mul_v3_fl(min_vel, 1.0f / sds->dx);
- mul_v3_fl(max_vel, 1.0f / sds->dx);
- clampBoundsInDomain(sds, min, max, min_vel, max_vel, sds->adapt_margin + 1, dt);
-
- for (int i = 0; i < 3; i++) {
- /* calculate new resolution */
- res[i] = max[i] - min[i];
- total_cells *= res[i];
-
- if (new_shift[i]) {
- shift_changed = 1;
- }
-
- /* if no content set minimum dimensions */
- if (res[i] <= 0) {
- int j;
- for (j = 0; j < 3; j++) {
- min[j] = 0;
- max[j] = 1;
- res[j] = 1;
- }
- res_changed = 1;
- total_cells = 1;
- break;
- }
- if (min[i] != sds->res_min[i] || max[i] != sds->res_max[i]) {
- res_changed = 1;
- }
- }
-
- if (res_changed || shift_changed) {
- struct FLUID_3D *fluid_old = sds->fluid;
- struct WTURBULENCE *turb_old = sds->wt;
- /* allocate new fluid data */
- BKE_smoke_reallocate_fluid(sds, sds->dx, res, 0);
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- BKE_smoke_reallocate_highres_fluid(sds, sds->dx, res, 0);
- }
-
- /* copy values from old fluid to new */
- if (sds->total_cells > 1 && total_cells > 1) {
- /* low res smoke */
- float *o_dens, *o_react, *o_flame, *o_fuel, *o_heat, *o_heatold, *o_vx, *o_vy, *o_vz, *o_r,
- *o_g, *o_b;
- float *n_dens, *n_react, *n_flame, *n_fuel, *n_heat, *n_heatold, *n_vx, *n_vy, *n_vz, *n_r,
- *n_g, *n_b;
- float dummy;
- unsigned char *dummy_p;
- /* high res smoke */
- int wt_res_old[3];
- float *o_wt_dens, *o_wt_react, *o_wt_flame, *o_wt_fuel, *o_wt_tcu, *o_wt_tcv, *o_wt_tcw,
- *o_wt_r, *o_wt_g, *o_wt_b;
- float *n_wt_dens, *n_wt_react, *n_wt_flame, *n_wt_fuel, *n_wt_tcu, *n_wt_tcv, *n_wt_tcw,
- *n_wt_r, *n_wt_g, *n_wt_b;
-
- smoke_export(fluid_old,
- &dummy,
- &dummy,
- &o_dens,
- &o_react,
- &o_flame,
- &o_fuel,
- &o_heat,
- &o_heatold,
- &o_vx,
- &o_vy,
- &o_vz,
- &o_r,
- &o_g,
- &o_b,
- &dummy_p);
- smoke_export(sds->fluid,
- &dummy,
- &dummy,
- &n_dens,
- &n_react,
- &n_flame,
- &n_fuel,
- &n_heat,
- &n_heatold,
- &n_vx,
- &n_vy,
- &n_vz,
- &n_r,
- &n_g,
- &n_b,
- &dummy_p);
-
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- smoke_turbulence_export(turb_old,
- &o_wt_dens,
- &o_wt_react,
- &o_wt_flame,
- &o_wt_fuel,
- &o_wt_r,
- &o_wt_g,
- &o_wt_b,
- &o_wt_tcu,
- &o_wt_tcv,
- &o_wt_tcw);
- smoke_turbulence_get_res(turb_old, wt_res_old);
- smoke_turbulence_export(sds->wt,
- &n_wt_dens,
- &n_wt_react,
- &n_wt_flame,
- &n_wt_fuel,
- &n_wt_r,
- &n_wt_g,
- &n_wt_b,
- &n_wt_tcu,
- &n_wt_tcv,
- &n_wt_tcw);
- }
-
- for (x = sds->res_min[0]; x < sds->res_max[0]; x++) {
- for (y = sds->res_min[1]; y < sds->res_max[1]; y++) {
- for (z = sds->res_min[2]; z < sds->res_max[2]; z++) {
- /* old grid index */
- int xo = x - sds->res_min[0];
- int yo = y - sds->res_min[1];
- int zo = z - sds->res_min[2];
- int index_old = smoke_get_index(xo, sds->res[0], yo, sds->res[1], zo);
- /* new grid index */
- int xn = x - min[0] - new_shift[0];
- int yn = y - min[1] - new_shift[1];
- int zn = z - min[2] - new_shift[2];
- int index_new = smoke_get_index(xn, res[0], yn, res[1], zn);
-
- /* skip if outside new domain */
- if (xn < 0 || xn >= res[0] || yn < 0 || yn >= res[1] || zn < 0 || zn >= res[2]) {
- continue;
- }
-
- /* copy data */
- n_dens[index_new] = o_dens[index_old];
- /* heat */
- if (n_heat && o_heat) {
- n_heat[index_new] = o_heat[index_old];
- n_heatold[index_new] = o_heatold[index_old];
- }
- /* fuel */
- if (n_fuel && o_fuel) {
- n_flame[index_new] = o_flame[index_old];
- n_fuel[index_new] = o_fuel[index_old];
- n_react[index_new] = o_react[index_old];
- }
- /* color */
- if (o_r && n_r) {
- n_r[index_new] = o_r[index_old];
- n_g[index_new] = o_g[index_old];
- n_b[index_new] = o_b[index_old];
- }
- n_vx[index_new] = o_vx[index_old];
- n_vy[index_new] = o_vy[index_old];
- n_vz[index_new] = o_vz[index_old];
-
- if (sds->flags & MOD_SMOKE_HIGHRES && turb_old) {
- 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;
- /* new grid index */
- int xx_n = xn * block_size;
- int yy_n = yn * block_size;
- int zz_n = zn * block_size;
-
- n_wt_tcu[index_new] = o_wt_tcu[index_old];
- n_wt_tcv[index_new] = o_wt_tcv[index_old];
- n_wt_tcw[index_new] = o_wt_tcw[index_old];
-
- for (i = 0; i < block_size; i++) {
- for (j = 0; j < block_size; j++) {
- for (k = 0; k < block_size; k++) {
- int big_index_old = smoke_get_index(
- xx_o + i, wt_res_old[0], yy_o + j, wt_res_old[1], zz_o + k);
- int big_index_new = smoke_get_index(
- xx_n + i, sds->res_wt[0], yy_n + j, sds->res_wt[1], zz_n + k);
- /* copy data */
- n_wt_dens[big_index_new] = o_wt_dens[big_index_old];
- if (n_wt_flame && o_wt_flame) {
- n_wt_flame[big_index_new] = o_wt_flame[big_index_old];
- n_wt_fuel[big_index_new] = o_wt_fuel[big_index_old];
- n_wt_react[big_index_new] = o_wt_react[big_index_old];
- }
- if (n_wt_r && o_wt_r) {
- n_wt_r[big_index_new] = o_wt_r[big_index_old];
- n_wt_g[big_index_new] = o_wt_g[big_index_old];
- n_wt_b[big_index_new] = o_wt_b[big_index_old];
- }
- }
- }
- }
- }
- }
- }
- }
- }
- smoke_free(fluid_old);
- if (turb_old) {
- smoke_turbulence_free(turb_old);
- }
-
- /* set new domain dimensions */
- copy_v3_v3_int(sds->res_min, min);
- copy_v3_v3_int(sds->res_max, max);
- copy_v3_v3_int(sds->res, res);
- sds->total_cells = total_cells;
- }
-}
-
-BLI_INLINE void apply_outflow_fields(int index,
- float *density,
- float *heat,
- float *fuel,
- float *react,
- float *color_r,
- float *color_g,
- float *color_b)
-{
- density[index] = 0.f;
- if (heat) {
- heat[index] = 0.f;
- }
- if (fuel) {
- fuel[index] = 0.f;
- react[index] = 0.f;
- }
- if (color_r) {
- color_r[index] = 0.f;
- color_g[index] = 0.f;
- color_b[index] = 0.f;
- }
-}
-
-BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs,
- float emission_value,
- int index,
- float *density,
- float *heat,
- float *fuel,
- float *react,
- float *color_r,
- float *color_g,
- float *color_b)
-{
- int absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE);
- float dens_old = density[index];
- // float fuel_old = (fuel) ? fuel[index] : 0.0f; /* UNUSED */
- float dens_flow = (sfs->type == MOD_SMOKE_FLOW_TYPE_FIRE) ? 0.0f : emission_value * sfs->density;
- float fuel_flow = emission_value * sfs->fuel_amount;
- /* add heat */
- if (heat && emission_value > 0.0f) {
- heat[index] = ADD_IF_LOWER(heat[index], sfs->temp);
- }
- /* absolute */
- if (absolute_flow) {
- if (sfs->type != MOD_SMOKE_FLOW_TYPE_FIRE) {
- if (dens_flow > density[index]) {
- density[index] = dens_flow;
- }
- }
- if (sfs->type != MOD_SMOKE_FLOW_TYPE_SMOKE && fuel && fuel_flow) {
- if (fuel_flow > fuel[index]) {
- fuel[index] = fuel_flow;
- }
- }
- }
- /* additive */
- else {
- if (sfs->type != MOD_SMOKE_FLOW_TYPE_FIRE) {
- density[index] += dens_flow;
- CLAMP(density[index], 0.0f, 1.0f);
- }
- if (sfs->type != MOD_SMOKE_FLOW_TYPE_SMOKE && fuel && sfs->fuel_amount) {
- fuel[index] += fuel_flow;
- CLAMP(fuel[index], 0.0f, 10.0f);
- }
- }
-
- /* set color */
- if (color_r && dens_flow) {
- float total_dens = density[index] / (dens_old + dens_flow);
- color_r[index] = (color_r[index] + sfs->color[0] * dens_flow) * total_dens;
- color_g[index] = (color_g[index] + sfs->color[1] * dens_flow) * total_dens;
- color_b[index] = (color_b[index] + sfs->color[2] * dens_flow) * total_dens;
- }
-
- /* set fire reaction coordinate */
- if (fuel && fuel[index] > FLT_EPSILON) {
- /* instead of using 1.0 for all new fuel add slight falloff
- * to reduce flow blockiness */
- float value = 1.0f - pow2f(1.0f - emission_value);
-
- if (value > react[index]) {
- float f = fuel_flow / fuel[index];
- react[index] = value * f + (1.0f - f) * react[index];
- CLAMP(react[index], 0.0f, value);
- }
- }
-}
-
-static void update_flowsfluids(
- Depsgraph *depsgraph, Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt)
-{
- Object **flowobjs = NULL;
- EmissionMap *emaps = NULL;
- unsigned int numflowobj = 0;
- unsigned int flowIndex;
- int new_shift[3] = {0};
- int active_fields = sds->active_fields;
-
- /* calculate domain shift for current frame if using adaptive domain */
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
- int total_shift[3];
- float frame_shift_f[3];
- float ob_loc[3] = {0};
-
- mul_m4_v3(ob->obmat, ob_loc);
-
- sub_v3_v3v3(frame_shift_f, ob_loc, sds->prev_loc);
- copy_v3_v3(sds->prev_loc, ob_loc);
- /* convert global space shift to local "cell" space */
- mul_mat3_m4_v3(sds->imat, frame_shift_f);
- frame_shift_f[0] = frame_shift_f[0] / sds->cell_size[0];
- frame_shift_f[1] = frame_shift_f[1] / sds->cell_size[1];
- frame_shift_f[2] = frame_shift_f[2] / sds->cell_size[2];
- /* add to total shift */
- add_v3_v3(sds->shift_f, frame_shift_f);
- /* convert to integer */
- total_shift[0] = (int)(floorf(sds->shift_f[0]));
- total_shift[1] = (int)(floorf(sds->shift_f[1]));
- total_shift[2] = (int)(floorf(sds->shift_f[2]));
- sub_v3_v3v3_int(new_shift, total_shift, sds->shift);
- copy_v3_v3_int(sds->shift, total_shift);
-
- /* calculate new domain boundary points so that smoke doesn't slide on sub-cell movement */
- sds->p0[0] = sds->dp0[0] - sds->cell_size[0] * (sds->shift_f[0] - total_shift[0] - 0.5f);
- sds->p0[1] = sds->dp0[1] - sds->cell_size[1] * (sds->shift_f[1] - total_shift[1] - 0.5f);
- sds->p0[2] = sds->dp0[2] - sds->cell_size[2] * (sds->shift_f[2] - total_shift[2] - 0.5f);
- sds->p1[0] = sds->p0[0] + sds->cell_size[0] * sds->base_res[0];
- sds->p1[1] = sds->p0[1] + sds->cell_size[1] * sds->base_res[1];
- sds->p1[2] = sds->p0[2] + sds->cell_size[2] * sds->base_res[2];
- }
-
- flowobjs = BKE_collision_objects_create(
- depsgraph, ob, sds->fluid_group, &numflowobj, eModifierType_Smoke);
-
- /* init emission maps for each flow */
- emaps = MEM_callocN(sizeof(struct EmissionMap) * numflowobj, "smoke_flow_maps");
-
- /* Prepare flow emission maps */
- for (flowIndex = 0; flowIndex < numflowobj; flowIndex++) {
- Object *collob = flowobjs[flowIndex];
- SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(collob,
- eModifierType_Smoke);
-
- // check for initialized smoke object
- if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) {
- // we got nice flow object
- SmokeFlowSettings *sfs = smd2->flow;
- int subframes = sfs->subframes;
- EmissionMap *em = &emaps[flowIndex];
-
- /* just sample flow directly to emission map if no subframes */
- if (!subframes) {
- if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) {
- emit_from_particles(collob, sds, sfs, em, depsgraph, scene, dt);
- }
- else {
- emit_from_mesh(collob, sds, sfs, em, dt);
- }
- }
- /* sample subframes */
- else {
- int scene_frame = (int)DEG_get_ctime(depsgraph);
- // float scene_subframe = scene->r.subframe; // UNUSED
- int subframe;
- for (subframe = 0; subframe <= subframes; subframe++) {
- EmissionMap em_temp = {NULL};
- float sample_size = 1.0f / (float)(subframes + 1);
- float prev_frame_pos = sample_size * (float)(subframe + 1);
- float sdt = dt * sample_size;
- int hires_multiplier = 1;
-
- if ((sds->flags & MOD_SMOKE_HIGHRES) && (sds->highres_sampling == SM_HRES_FULLSAMPLE)) {
- hires_multiplier = sds->amplify + 1;
- }
-
- /* set scene frame to match previous frame + subframe
- * or use current frame for last sample */
- if (subframe < subframes) {
- scene->r.cfra = scene_frame - 1;
- scene->r.subframe = prev_frame_pos;
- }
- else {
- scene->r.cfra = scene_frame;
- scene->r.subframe = 0.0f;
- }
-
- /* update flow object frame */
- BLI_mutex_lock(&object_update_lock);
- BKE_object_modifier_update_subframe(
- depsgraph, scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke);
- BLI_mutex_unlock(&object_update_lock);
-
- if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) {
- /* emit_from_particles() updates timestep internally */
- emit_from_particles(collob, sds, sfs, &em_temp, depsgraph, scene, sdt);
- if (!(sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE)) {
- hires_multiplier = 1;
- }
- }
- else { /* MOD_SMOKE_FLOW_SOURCE_MESH */
- /* apply flow */
- emit_from_mesh(collob, sds, sfs, &em_temp, sdt);
- }
-
- /* combine emission maps */
- em_combineMaps(em,
- &em_temp,
- hires_multiplier,
- !(sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE),
- sample_size);
- em_freeData(&em_temp);
- }
- }
-
- /* update required data fields */
- if (em->total_cells && sfs->type != MOD_SMOKE_FLOW_TYPE_OUTFLOW) {
- /* activate heat field if flow produces any heat */
- if (sfs->temp) {
- active_fields |= SM_ACTIVE_HEAT;
- }
- /* activate fuel field if flow adds any fuel */
- if (sfs->type != MOD_SMOKE_FLOW_TYPE_SMOKE && sfs->fuel_amount) {
- active_fields |= SM_ACTIVE_FIRE;
- }
- /* activate color field if flows add smoke with varying colors */
- if (sfs->type != MOD_SMOKE_FLOW_TYPE_FIRE && sfs->density) {
- if (!(active_fields & SM_ACTIVE_COLOR_SET)) {
- copy_v3_v3(sds->active_color, sfs->color);
- active_fields |= SM_ACTIVE_COLOR_SET;
- }
- else if (!equals_v3v3(sds->active_color, sfs->color)) {
- copy_v3_v3(sds->active_color, sfs->color);
- active_fields |= SM_ACTIVE_COLORS;
- }
- }
- }
- }
- }
-
- /* monitor active fields based on domain settings */
- /* if domain has fire, activate new fields if required */
- if (active_fields & SM_ACTIVE_FIRE) {
- /* heat is always needed for fire */
- active_fields |= SM_ACTIVE_HEAT;
- /* also activate colors if domain smoke color differs from active color */
- if (!(active_fields & SM_ACTIVE_COLOR_SET)) {
- copy_v3_v3(sds->active_color, sds->flame_smoke_color);
- active_fields |= SM_ACTIVE_COLOR_SET;
- }
- else if (!equals_v3v3(sds->active_color, sds->flame_smoke_color)) {
- copy_v3_v3(sds->active_color, sds->flame_smoke_color);
- active_fields |= SM_ACTIVE_COLORS;
- }
- }
-
- /* Adjust domain size if needed */
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
- adjustDomainResolution(sds, new_shift, emaps, numflowobj, dt);
- }
-
- /* Initialize new data fields if any */
- if (active_fields & SM_ACTIVE_HEAT) {
- smoke_ensure_heat(sds->fluid);
- }
- if (active_fields & SM_ACTIVE_FIRE) {
- smoke_ensure_fire(sds->fluid, sds->wt);
- }
- if (active_fields & SM_ACTIVE_COLORS) {
- /* initialize all smoke with "active_color" */
- smoke_ensure_colors(
- sds->fluid, sds->wt, sds->active_color[0], sds->active_color[1], sds->active_color[2]);
- }
- sds->active_fields = active_fields;
-
- /* Apply emission data */
- if (sds->fluid) {
- for (flowIndex = 0; flowIndex < numflowobj; flowIndex++) {
- Object *collob = flowobjs[flowIndex];
- SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(collob,
- eModifierType_Smoke);
-
- // check for initialized smoke object
- if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) {
- // we got nice flow object
- SmokeFlowSettings *sfs = smd2->flow;
- EmissionMap *em = &emaps[flowIndex];
-
- float *density = smoke_get_density(sds->fluid);
- float *color_r = smoke_get_color_r(sds->fluid);
- float *color_g = smoke_get_color_g(sds->fluid);
- float *color_b = smoke_get_color_b(sds->fluid);
- float *fuel = smoke_get_fuel(sds->fluid);
- float *react = smoke_get_react(sds->fluid);
- float *bigdensity = smoke_turbulence_get_density(sds->wt);
- float *bigfuel = smoke_turbulence_get_fuel(sds->wt);
- float *bigreact = smoke_turbulence_get_react(sds->wt);
- float *bigcolor_r = smoke_turbulence_get_color_r(sds->wt);
- float *bigcolor_g = smoke_turbulence_get_color_g(sds->wt);
- float *bigcolor_b = smoke_turbulence_get_color_b(sds->wt);
- float *heat = smoke_get_heat(sds->fluid);
- float *velocity_x = smoke_get_velocity_x(sds->fluid);
- float *velocity_y = smoke_get_velocity_y(sds->fluid);
- float *velocity_z = smoke_get_velocity_z(sds->fluid);
- // unsigned char *obstacle = smoke_get_obstacle(sds->fluid);
- // DG TODO UNUSED unsigned char *obstacleAnim = smoke_get_obstacle_anim(sds->fluid);
- int bigres[3];
- float *velocity_map = em->velocity;
- float *emission_map = em->influence;
- float *emission_map_high = em->influence_high;
-
- int ii, jj, kk, gx, gy, gz, ex, ey, ez, dx, dy, dz, block_size;
- size_t e_index, d_index, index_big;
-
- // loop through every emission map cell
- for (gx = em->min[0]; gx < em->max[0]; gx++) {
- for (gy = em->min[1]; gy < em->max[1]; gy++) {
- for (gz = em->min[2]; gz < em->max[2]; gz++) {
- /* get emission map index */
- ex = gx - em->min[0];
- ey = gy - em->min[1];
- ez = gz - em->min[2];
- e_index = smoke_get_index(ex, em->res[0], ey, em->res[1], ez);
-
- /* get domain index */
- dx = gx - sds->res_min[0];
- dy = gy - sds->res_min[1];
- dz = gz - sds->res_min[2];
- d_index = smoke_get_index(dx, sds->res[0], dy, sds->res[1], dz);
- /* make sure emission cell is inside the new domain boundary */
- if (dx < 0 || dy < 0 || dz < 0 || dx >= sds->res[0] || dy >= sds->res[1] ||
- dz >= sds->res[2]) {
- continue;
- }
-
- if (sfs->type == MOD_SMOKE_FLOW_TYPE_OUTFLOW) { // outflow
- apply_outflow_fields(
- d_index, density, heat, fuel, react, color_r, color_g, color_b);
- }
- else { // inflow
- apply_inflow_fields(sfs,
- emission_map[e_index],
- d_index,
- density,
- heat,
- fuel,
- react,
- color_r,
- color_g,
- color_b);
-
- /* initial velocity */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) {
- velocity_x[d_index] = ADD_IF_LOWER(velocity_x[d_index],
- velocity_map[e_index * 3]);
- velocity_y[d_index] = ADD_IF_LOWER(velocity_y[d_index],
- velocity_map[e_index * 3 + 1]);
- velocity_z[d_index] = ADD_IF_LOWER(velocity_z[d_index],
- velocity_map[e_index * 3 + 2]);
- }
- }
-
- /* loop through high res blocks if high res enabled */
- if (bigdensity) {
- /* Neighbor cell emission densities
- * (for high resolution smoke smooth interpolation). */
- float c000, c001, c010, c011, c100, c101, c110, c111;
-
- smoke_turbulence_get_res(sds->wt, bigres);
- block_size = sds->amplify + 1; // high res block size
-
- c000 = (ex > 0 && ey > 0 && ez > 0) ?
- emission_map[smoke_get_index(
- ex - 1, em->res[0], ey - 1, em->res[1], ez - 1)] :
- 0;
- c001 =
- (ex > 0 && ey > 0) ?
- emission_map[smoke_get_index(ex - 1, em->res[0], ey - 1, em->res[1], ez)] :
- 0;
- c010 =
- (ex > 0 && ez > 0) ?
- emission_map[smoke_get_index(ex - 1, em->res[0], ey, em->res[1], ez - 1)] :
- 0;
- c011 = (ex > 0) ?
- emission_map[smoke_get_index(ex - 1, em->res[0], ey, em->res[1], ez)] :
- 0;
-
- c100 =
- (ey > 0 && ez > 0) ?
- emission_map[smoke_get_index(ex, em->res[0], ey - 1, em->res[1], ez - 1)] :
- 0;
- c101 = (ey > 0) ?
- emission_map[smoke_get_index(ex, em->res[0], ey - 1, em->res[1], ez)] :
- 0;
- c110 = (ez > 0) ?
- emission_map[smoke_get_index(ex, em->res[0], ey, em->res[1], ez - 1)] :
- 0;
- c111 = emission_map[smoke_get_index(
- ex, em->res[0], ey, em->res[1], ez)]; // this cell
-
- for (ii = 0; ii < block_size; ii++) {
- for (jj = 0; jj < block_size; jj++) {
- for (kk = 0; kk < block_size; kk++) {
-
- float fx, fy, fz, interpolated_value;
- int shift_x = 0, shift_y = 0, shift_z = 0;
-
- /* Use full sample emission map if enabled and available */
- if ((sds->highres_sampling == SM_HRES_FULLSAMPLE) && emission_map_high) {
- interpolated_value =
- emission_map_high[smoke_get_index(ex * block_size + ii,
- em->res[0] * block_size,
- ey * block_size + jj,
- em->res[1] * block_size,
- ez * block_size + kk)]; // this cell
- }
- else if (sds->highres_sampling == SM_HRES_NEAREST) {
- /* without interpolation use same low resolution
- * block value for all hi-res blocks */
- interpolated_value = c111;
- }
- /* Fall back to interpolated */
- else {
- /* get relative block position
- * for interpolation smoothing */
- fx = (float)ii / block_size + 0.5f / block_size;
- fy = (float)jj / block_size + 0.5f / block_size;
- fz = (float)kk / block_size + 0.5f / block_size;
-
- /* calculate trilinear interpolation */
- interpolated_value = c000 * (1 - fx) * (1 - fy) * (1 - fz) +
- c100 * fx * (1 - fy) * (1 - fz) +
- c010 * (1 - fx) * fy * (1 - fz) +
- c001 * (1 - fx) * (1 - fy) * fz +
- c101 * fx * (1 - fy) * fz +
- c011 * (1 - fx) * fy * fz +
- c110 * fx * fy * (1 - fz) + c111 * fx * fy * fz;
-
- /* add some contrast / sharpness
- * depending on hi-res block size */
- interpolated_value = (interpolated_value - 0.4f) * (block_size / 2) + 0.4f;
- CLAMP(interpolated_value, 0.0f, 1.0f);
-
- /* shift smoke block index
- * (because pixel center is actually
- * in halfway of the low res block) */
- shift_x = (dx < 1) ? 0 : block_size / 2;
- shift_y = (dy < 1) ? 0 : block_size / 2;
- shift_z = (dz < 1) ? 0 : block_size / 2;
- }
-
- /* get shifted index for current high resolution block */
- index_big = smoke_get_index(block_size * dx + ii - shift_x,
- bigres[0],
- block_size * dy + jj - shift_y,
- bigres[1],
- block_size * dz + kk - shift_z);
-
- if (sfs->type == MOD_SMOKE_FLOW_TYPE_OUTFLOW) { // outflow
- if (interpolated_value) {
- apply_outflow_fields(index_big,
- bigdensity,
- NULL,
- bigfuel,
- bigreact,
- bigcolor_r,
- bigcolor_g,
- bigcolor_b);
- }
- }
- else { // inflow
- apply_inflow_fields(sfs,
- interpolated_value,
- index_big,
- bigdensity,
- NULL,
- bigfuel,
- bigreact,
- bigcolor_r,
- bigcolor_g,
- bigcolor_b);
- }
- } // hires loop
- }
- }
- } // bigdensity
- } // low res loop
- }
- }
-
- // free emission maps
- em_freeData(em);
-
- } // end emission
- }
- }
-
- BKE_collision_objects_free(flowobjs);
- if (emaps) {
- MEM_freeN(emaps);
- }
-}
-
-typedef struct UpdateEffectorsData {
- Scene *scene;
- SmokeDomainSettings *sds;
- ListBase *effectors;
-
- float *density;
- float *fuel;
- float *force_x;
- float *force_y;
- float *force_z;
- float *velocity_x;
- float *velocity_y;
- float *velocity_z;
- unsigned char *obstacle;
-} UpdateEffectorsData;
-
-static void update_effectors_task_cb(void *__restrict userdata,
- const int x,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- UpdateEffectorsData *data = userdata;
- SmokeDomainSettings *sds = data->sds;
-
- for (int y = 0; y < sds->res[1]; y++) {
- for (int z = 0; z < sds->res[2]; z++) {
- EffectedPoint epoint;
- float mag;
- float voxelCenter[3] = {0, 0, 0}, vel[3] = {0, 0, 0}, retvel[3] = {0, 0, 0};
- const unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
-
- if (((data->fuel ? MAX2(data->density[index], data->fuel[index]) : data->density[index]) <
- FLT_EPSILON) ||
- data->obstacle[index]) {
- continue;
- }
-
- vel[0] = data->velocity_x[index];
- vel[1] = data->velocity_y[index];
- vel[2] = data->velocity_z[index];
-
- /* convert vel to global space */
- mag = len_v3(vel);
- mul_mat3_m4_v3(sds->obmat, vel);
- normalize_v3(vel);
- mul_v3_fl(vel, mag);
-
- voxelCenter[0] = sds->p0[0] + sds->cell_size[0] * ((float)(x + sds->res_min[0]) + 0.5f);
- voxelCenter[1] = sds->p0[1] + sds->cell_size[1] * ((float)(y + sds->res_min[1]) + 0.5f);
- voxelCenter[2] = sds->p0[2] + sds->cell_size[2] * ((float)(z + sds->res_min[2]) + 0.5f);
- mul_m4_v3(sds->obmat, voxelCenter);
-
- pd_point_from_loc(data->scene, voxelCenter, vel, index, &epoint);
- BKE_effectors_apply(data->effectors, NULL, sds->effector_weights, &epoint, retvel, NULL);
-
- /* convert retvel to local space */
- mag = len_v3(retvel);
- mul_mat3_m4_v3(sds->imat, retvel);
- normalize_v3(retvel);
- mul_v3_fl(retvel, mag);
-
- // TODO dg - do in force!
- data->force_x[index] = min_ff(max_ff(-1.0f, retvel[0] * 0.2f), 1.0f);
- data->force_y[index] = min_ff(max_ff(-1.0f, retvel[1] * 0.2f), 1.0f);
- data->force_z[index] = min_ff(max_ff(-1.0f, retvel[2] * 0.2f), 1.0f);
- }
- }
-}
-
-static void update_effectors(
- Depsgraph *depsgraph, Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt))
-{
- ListBase *effectors;
- /* make sure smoke flow influence is 0.0f */
- sds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f;
- effectors = BKE_effectors_create(depsgraph, ob, NULL, sds->effector_weights);
-
- if (effectors) {
- // precalculate wind forces
- UpdateEffectorsData data;
- data.scene = scene;
- data.sds = sds;
- data.effectors = effectors;
- data.density = smoke_get_density(sds->fluid);
- data.fuel = smoke_get_fuel(sds->fluid);
- data.force_x = smoke_get_force_x(sds->fluid);
- data.force_y = smoke_get_force_y(sds->fluid);
- data.force_z = smoke_get_force_z(sds->fluid);
- data.velocity_x = smoke_get_velocity_x(sds->fluid);
- data.velocity_y = smoke_get_velocity_y(sds->fluid);
- data.velocity_z = smoke_get_velocity_z(sds->fluid);
- data.obstacle = smoke_get_obstacle(sds->fluid);
-
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
- BLI_task_parallel_range(0, sds->res[0], &data, update_effectors_task_cb, &settings);
- }
-
- BKE_effectors_free(effectors);
-}
-
-static void step(Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- SmokeModifierData *smd,
- Mesh *domain_me,
- float fps)
-{
- SmokeDomainSettings *sds = smd->domain;
- /* stability values copied from wturbulence.cpp */
- const int maxSubSteps = 25;
- float maxVel;
- // maxVel should be 1.5 (1.5 cell max movement) * dx (cell size)
-
- float dt;
- float maxVelMag = 0.0f;
- int totalSubsteps;
- int substep = 0;
- float dtSubdiv;
- float gravity[3] = {0.0f, 0.0f, -1.0f};
- float gravity_mag;
-
- /* update object state */
- invert_m4_m4(sds->imat, ob->obmat);
- copy_m4_m4(sds->obmat, ob->obmat);
- smoke_set_domain_from_mesh(sds, ob, domain_me, (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) != 0);
-
- /* use global gravity if enabled */
- if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
- copy_v3_v3(gravity, scene->physics_settings.gravity);
- /* map default value to 1.0 */
- mul_v3_fl(gravity, 1.0f / 9.810f);
- }
- /* convert gravity to domain space */
- gravity_mag = len_v3(gravity);
- mul_mat3_m4_v3(sds->imat, gravity);
- normalize_v3(gravity);
- mul_v3_fl(gravity, gravity_mag);
-
- /* adapt timestep for different framerates, dt = 0.1 is at 25fps */
- dt = DT_DEFAULT * (25.0f / fps);
- // maximum timestep/"CFL" constraint: dt < 5.0 *dx / maxVel
- maxVel = (sds->dx * 5.0f);
-
- maxVelMag = sqrtf(maxVelMag) * dt * sds->time_scale;
- totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */
- totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
- totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
-
- /* Disable substeps for now, since it results in numerical instability */
- totalSubsteps = 1.0f;
-
- dtSubdiv = (float)dt / (float)totalSubsteps;
-
- // printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt);
-
- for (substep = 0; substep < totalSubsteps; substep++) {
- // calc animated obstacle velocities
- update_flowsfluids(depsgraph, scene, ob, sds, dtSubdiv);
- update_obstacles(depsgraph, ob, sds, dtSubdiv, substep, totalSubsteps);
-
- if (sds->total_cells > 1) {
- // DG TODO? problem --> uses forces instead of velocity,
- // need to check how they need to be changed with variable dt.
- update_effectors(depsgraph, scene, ob, sds, dtSubdiv);
- smoke_step(sds->fluid, gravity, dtSubdiv);
- }
- }
-}
-
-static Mesh *createDomainGeometry(SmokeDomainSettings *sds, Object *ob)
-{
- Mesh *result;
- MVert *mverts;
- MPoly *mpolys;
- MLoop *mloops;
- float min[3];
- float max[3];
- float *co;
- MPoly *mp;
- MLoop *ml;
-
- int num_verts = 8;
- int num_faces = 6;
- int i;
- float ob_loc[3] = {0};
- float ob_cache_loc[3] = {0};
-
- /* dont generate any mesh if there isnt any content */
- if (sds->total_cells <= 1) {
- num_verts = 0;
- num_faces = 0;
- }
-
- result = BKE_mesh_new_nomain(num_verts, 0, 0, num_faces * 4, num_faces);
- mverts = result->mvert;
- mpolys = result->mpoly;
- mloops = result->mloop;
-
- if (num_verts) {
- /* volume bounds */
- madd_v3fl_v3fl_v3fl_v3i(min, sds->p0, sds->cell_size, sds->res_min);
- madd_v3fl_v3fl_v3fl_v3i(max, sds->p0, sds->cell_size, sds->res_max);
-
- /* set vertices */
- /* top slab */
- co = mverts[0].co;
- co[0] = min[0];
- co[1] = min[1];
- co[2] = max[2];
- co = mverts[1].co;
- co[0] = max[0];
- co[1] = min[1];
- co[2] = max[2];
- co = mverts[2].co;
- co[0] = max[0];
- co[1] = max[1];
- co[2] = max[2];
- co = mverts[3].co;
- co[0] = min[0];
- co[1] = max[1];
- co[2] = max[2];
- /* bottom slab */
- co = mverts[4].co;
- co[0] = min[0];
- co[1] = min[1];
- co[2] = min[2];
- co = mverts[5].co;
- co[0] = max[0];
- co[1] = min[1];
- co[2] = min[2];
- co = mverts[6].co;
- co[0] = max[0];
- co[1] = max[1];
- co[2] = min[2];
- co = mverts[7].co;
- co[0] = min[0];
- co[1] = max[1];
- co[2] = min[2];
-
- /* create faces */
- /* top */
- mp = &mpolys[0];
- ml = &mloops[0 * 4];
- mp->loopstart = 0 * 4;
- mp->totloop = 4;
- ml[0].v = 0;
- ml[1].v = 1;
- ml[2].v = 2;
- ml[3].v = 3;
- /* right */
- mp = &mpolys[1];
- ml = &mloops[1 * 4];
- mp->loopstart = 1 * 4;
- mp->totloop = 4;
- ml[0].v = 2;
- ml[1].v = 1;
- ml[2].v = 5;
- ml[3].v = 6;
- /* bottom */
- mp = &mpolys[2];
- ml = &mloops[2 * 4];
- mp->loopstart = 2 * 4;
- mp->totloop = 4;
- ml[0].v = 7;
- ml[1].v = 6;
- ml[2].v = 5;
- ml[3].v = 4;
- /* left */
- mp = &mpolys[3];
- ml = &mloops[3 * 4];
- mp->loopstart = 3 * 4;
- mp->totloop = 4;
- ml[0].v = 0;
- ml[1].v = 3;
- ml[2].v = 7;
- ml[3].v = 4;
- /* front */
- mp = &mpolys[4];
- ml = &mloops[4 * 4];
- mp->loopstart = 4 * 4;
- mp->totloop = 4;
- ml[0].v = 3;
- ml[1].v = 2;
- ml[2].v = 6;
- ml[3].v = 7;
- /* back */
- mp = &mpolys[5];
- ml = &mloops[5 * 4];
- mp->loopstart = 5 * 4;
- mp->totloop = 4;
- ml[0].v = 1;
- ml[1].v = 0;
- ml[2].v = 4;
- ml[3].v = 5;
-
- /* calculate required shift to match domain's global position
- * it was originally simulated at (if object moves without smoke step) */
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->obmat, ob_loc);
- mul_m4_v3(sds->obmat, ob_cache_loc);
- sub_v3_v3v3(sds->obj_shift_f, ob_cache_loc, ob_loc);
- /* convert shift to local space and apply to vertices */
- mul_mat3_m4_v3(ob->imat, sds->obj_shift_f);
- /* apply */
- for (i = 0; i < num_verts; i++) {
- add_v3_v3(mverts[i].co, sds->obj_shift_f);
- }
- }
-
- BKE_mesh_calc_edges(result, false, false);
- result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
- return result;
-}
-
-static void smokeModifier_process(
- SmokeModifierData *smd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me)
-{
- const int scene_framenr = (int)DEG_get_ctime(depsgraph);
-
- if ((smd->type & MOD_SMOKE_TYPE_FLOW)) {
- if (scene_framenr >= smd->time) {
- smokeModifier_init(smd, ob, scene_framenr, me);
- }
-
- if (smd->flow->mesh) {
- BKE_id_free(NULL, smd->flow->mesh);
- }
- smd->flow->mesh = BKE_mesh_copy_for_eval(me, false);
-
- if (scene_framenr > smd->time) {
- smd->time = scene_framenr;
- }
- else if (scene_framenr < smd->time) {
- smd->time = scene_framenr;
- smokeModifier_reset_ex(smd, false);
- }
- }
- else if (smd->type & MOD_SMOKE_TYPE_COLL) {
- if (scene_framenr >= smd->time) {
- smokeModifier_init(smd, ob, scene_framenr, me);
- }
-
- if (smd->coll) {
- if (smd->coll->mesh) {
- BKE_id_free(NULL, smd->coll->mesh);
- }
-
- smd->coll->mesh = BKE_mesh_copy_for_eval(me, false);
- }
-
- smd->time = scene_framenr;
- if (scene_framenr < smd->time) {
- smokeModifier_reset_ex(smd, false);
- }
- }
- else if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- SmokeDomainSettings *sds = smd->domain;
- PointCache *cache = NULL;
- PTCacheID pid;
- int startframe, endframe, framenr;
- float timescale;
-
- framenr = scene_framenr;
-
- cache = sds->point_cache[0];
- BKE_ptcache_id_from_smoke(&pid, ob, smd);
- BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
-
- if (!smd->domain->fluid || framenr == startframe) {
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- smokeModifier_reset_ex(smd, false);
- BKE_ptcache_validate(cache, framenr);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- }
-
- if (!smd->domain->fluid && (framenr != startframe) &&
- (smd->domain->flags & MOD_SMOKE_FILE_LOAD) == 0 && (cache->flag & PTCACHE_BAKED) == 0) {
- return;
- }
-
- smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD;
- CLAMP(framenr, startframe, endframe);
-
- /* If already viewing a pre/after frame, no need to reload */
- if ((smd->time == framenr) && (framenr != scene_framenr)) {
- return;
- }
-
- if (smokeModifier_init(smd, ob, scene_framenr, me) == 0) {
- printf("bad smokeModifier_init\n");
- return;
- }
-
- /* only calculate something when we advanced a single frame */
- /* don't simulate if viewing start frame, but scene frame is not real start frame */
- bool can_simulate = (framenr == (int)smd->time + 1) && (framenr == scene_framenr);
-
- /* try to read from cache */
- if (BKE_ptcache_read(&pid, (float)framenr, can_simulate) == PTCACHE_READ_EXACT) {
- BKE_ptcache_validate(cache, framenr);
- smd->time = framenr;
- return;
- }
-
- if (!can_simulate) {
- return;
- }
-
-# ifdef DEBUG_TIME
- double start = PIL_check_seconds_timer();
-# endif
-
- /* if on second frame, write cache for first frame */
- if ((int)smd->time == startframe &&
- (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
- BKE_ptcache_write(&pid, startframe);
- }
-
- // set new time
- smd->time = scene_framenr;
-
- /* do simulation */
-
- // simulate the actual smoke (c++ code in intern/smoke)
- // DG: interesting commenting this line + deactivating loading of noise files
- if (framenr != startframe) {
- if (sds->flags & MOD_SMOKE_DISSOLVE) {
- /* low res dissolve */
- smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
- /* high res dissolve */
- if (sds->wt) {
- smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG);
- }
- }
-
- step(depsgraph, scene, ob, smd, me, scene->r.frs_sec / scene->r.frs_sec_base);
- }
-
- // create shadows before writing cache so they get stored
- smoke_calc_transparency(sds, DEG_get_evaluated_view_layer(depsgraph));
-
- if (sds->wt && sds->total_cells > 1) {
- smoke_turbulence_step(sds->wt, sds->fluid);
- }
-
- BKE_ptcache_validate(cache, framenr);
- if (framenr != startframe) {
- BKE_ptcache_write(&pid, framenr);
- }
-
-# ifdef DEBUG_TIME
- double end = PIL_check_seconds_timer();
- printf("Frame: %d, Time: %f\n\n", (int)smd->time, (float)(end - start));
-# endif
- }
-}
-
-struct Mesh *smokeModifier_do(
- SmokeModifierData *smd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me)
-{
- /* lock so preview render does not read smoke data while it gets modified */
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- BLI_rw_mutex_lock(smd->domain->fluid_mutex, THREAD_LOCK_WRITE);
- }
-
- smokeModifier_process(smd, depsgraph, scene, ob, me);
-
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- BLI_rw_mutex_unlock(smd->domain->fluid_mutex);
- }
-
- /* return generated geometry for adaptive domain */
- Mesh *result;
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain &&
- smd->domain->flags & MOD_SMOKE_ADAPTIVE_DOMAIN && smd->domain->base_res[0]) {
- result = createDomainGeometry(smd->domain, ob);
- BKE_mesh_copy_settings(result, me);
- }
- else {
- result = BKE_mesh_copy_for_eval(me, false);
- }
-
- /* Smoke simulation needs a texture space relative to the adaptive domain bounds, not the
- * original mesh. So recompute it at this point in the modifier stack. See T58492. */
- BKE_mesh_texspace_calc(result);
-
- return result;
-}
-
-static float calc_voxel_transp(
- float *result, float *input, int res[3], int *pixel, float *tRay, float correct)
-{
- const size_t index = smoke_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]);
-
- // T_ray *= T_vox
- *tRay *= expf(input[index] * correct);
-
- if (result[index] < 0.0f) {
- result[index] = *tRay;
- }
-
- return *tRay;
-}
-
-static void bresenham_linie_3D(int x1,
- int y1,
- int z1,
- int x2,
- int y2,
- int z2,
- float *tRay,
- bresenham_callback cb,
- float *result,
- float *input,
- int res[3],
- float correct)
-{
- int dx, dy, dz, i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2;
- int pixel[3];
-
- pixel[0] = x1;
- pixel[1] = y1;
- pixel[2] = z1;
-
- dx = x2 - x1;
- dy = y2 - y1;
- dz = z2 - z1;
-
- x_inc = (dx < 0) ? -1 : 1;
- l = abs(dx);
- y_inc = (dy < 0) ? -1 : 1;
- m = abs(dy);
- z_inc = (dz < 0) ? -1 : 1;
- n = abs(dz);
- dx2 = l << 1;
- dy2 = m << 1;
- dz2 = n << 1;
-
- if ((l >= m) && (l >= n)) {
- err_1 = dy2 - l;
- err_2 = dz2 - l;
- for (i = 0; i < l; i++) {
- if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) {
- break;
- }
- if (err_1 > 0) {
- pixel[1] += y_inc;
- err_1 -= dx2;
- }
- if (err_2 > 0) {
- pixel[2] += z_inc;
- err_2 -= dx2;
- }
- err_1 += dy2;
- err_2 += dz2;
- pixel[0] += x_inc;
- }
- }
- else if ((m >= l) && (m >= n)) {
- err_1 = dx2 - m;
- err_2 = dz2 - m;
- for (i = 0; i < m; i++) {
- if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) {
- break;
- }
- if (err_1 > 0) {
- pixel[0] += x_inc;
- err_1 -= dy2;
- }
- if (err_2 > 0) {
- pixel[2] += z_inc;
- err_2 -= dy2;
- }
- err_1 += dx2;
- err_2 += dz2;
- pixel[1] += y_inc;
- }
- }
- else {
- err_1 = dy2 - n;
- err_2 = dx2 - n;
- for (i = 0; i < n; i++) {
- if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) {
- break;
- }
- if (err_1 > 0) {
- pixel[1] += y_inc;
- err_1 -= dz2;
- }
- if (err_2 > 0) {
- pixel[0] += x_inc;
- err_2 -= dz2;
- }
- err_1 += dy2;
- err_2 += dx2;
- pixel[2] += z_inc;
- }
- }
- cb(result, input, res, pixel, tRay, correct);
-}
-
-static void smoke_calc_transparency(SmokeDomainSettings *sds, ViewLayer *view_layer)
-{
- float bv[6] = {0};
- float light[3];
- int a, z, slabsize = sds->res[0] * sds->res[1], size = sds->res[0] * sds->res[1] * sds->res[2];
- float *density = smoke_get_density(sds->fluid);
- float correct = -7.0f * sds->dx;
-
- if (!get_light(view_layer, light)) {
- return;
- }
-
- /* convert light pos to sim cell space */
- mul_m4_v3(sds->imat, light);
- light[0] = (light[0] - sds->p0[0]) / sds->cell_size[0] - 0.5f - (float)sds->res_min[0];
- light[1] = (light[1] - sds->p0[1]) / sds->cell_size[1] - 0.5f - (float)sds->res_min[1];
- light[2] = (light[2] - sds->p0[2]) / sds->cell_size[2] - 0.5f - (float)sds->res_min[2];
-
- for (a = 0; a < size; a++) {
- sds->shadow[a] = -1.0f;
- }
-
- /* calculate domain bounds in sim cell space */
- // 0,2,4 = 0.0f
- bv[1] = (float)sds->res[0]; // x
- bv[3] = (float)sds->res[1]; // y
- bv[5] = (float)sds->res[2]; // z
-
- for (z = 0; z < sds->res[2]; z++) {
- size_t index = z * slabsize;
- int x, y;
-
- for (y = 0; y < sds->res[1]; y++) {
- for (x = 0; x < sds->res[0]; x++, index++) {
- float voxelCenter[3];
- float pos[3];
- int cell[3];
- float tRay = 1.0;
-
- if (sds->shadow[index] >= 0.0f) {
- continue;
- }
- voxelCenter[0] = (float)x;
- voxelCenter[1] = (float)y;
- voxelCenter[2] = (float)z;
-
- // get starting cell (light pos)
- if (BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON) {
- // we're outside -> use point on side of domain
- cell[0] = (int)floor(pos[0]);
- cell[1] = (int)floor(pos[1]);
- cell[2] = (int)floor(pos[2]);
- }
- else {
- // we're inside -> use light itself
- cell[0] = (int)floor(light[0]);
- cell[1] = (int)floor(light[1]);
- cell[2] = (int)floor(light[2]);
- }
- /* clamp within grid bounds */
- CLAMP(cell[0], 0, sds->res[0] - 1);
- CLAMP(cell[1], 0, sds->res[1] - 1);
- CLAMP(cell[2], 0, sds->res[2] - 1);
-
- bresenham_linie_3D(cell[0],
- cell[1],
- cell[2],
- x,
- y,
- z,
- &tRay,
- calc_voxel_transp,
- sds->shadow,
- density,
- sds->res,
- correct);
-
- // convention -> from a RGBA float array, use G value for tRay
- sds->shadow[index] = tRay;
- }
- }
- }
-}
-
-/* get smoke velocity and density at given coordinates
- * returns fluid density or -1.0f if outside domain. */
-float BKE_smoke_get_velocity_at(struct Object *ob, float position[3], float velocity[3])
-{
- SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
- zero_v3(velocity);
-
- if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && smd->domain->fluid) {
- SmokeDomainSettings *sds = smd->domain;
- float time_mult = 25.f * DT_DEFAULT;
- float vel_mag;
- float *velX = smoke_get_velocity_x(sds->fluid);
- float *velY = smoke_get_velocity_y(sds->fluid);
- float *velZ = smoke_get_velocity_z(sds->fluid);
- float density = 0.0f, fuel = 0.0f;
- float pos[3];
- copy_v3_v3(pos, position);
- smoke_pos_to_cell(sds, pos);
-
- /* check if point is outside domain max bounds */
- if (pos[0] < sds->res_min[0] || pos[1] < sds->res_min[1] || pos[2] < sds->res_min[2]) {
- return -1.0f;
- }
- if (pos[0] > sds->res_max[0] || pos[1] > sds->res_max[1] || pos[2] > sds->res_max[2]) {
- return -1.0f;
- }
-
- /* map pos between 0.0 - 1.0 */
- pos[0] = (pos[0] - sds->res_min[0]) / ((float)sds->res[0]);
- pos[1] = (pos[1] - sds->res_min[1]) / ((float)sds->res[1]);
- pos[2] = (pos[2] - sds->res_min[2]) / ((float)sds->res[2]);
-
- /* check if point is outside active area */
- if (smd->domain->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
- if (pos[0] < 0.0f || pos[1] < 0.0f || pos[2] < 0.0f) {
- return 0.0f;
- }
- if (pos[0] > 1.0f || pos[1] > 1.0f || pos[2] > 1.0f) {
- return 0.0f;
- }
- }
-
- /* get interpolated velocity */
- velocity[0] = BLI_voxel_sample_trilinear(velX, sds->res, pos) * sds->global_size[0] *
- time_mult;
- velocity[1] = BLI_voxel_sample_trilinear(velY, sds->res, pos) * sds->global_size[1] *
- time_mult;
- velocity[2] = BLI_voxel_sample_trilinear(velZ, sds->res, pos) * sds->global_size[2] *
- time_mult;
-
- /* convert velocity direction to global space */
- vel_mag = len_v3(velocity);
- mul_mat3_m4_v3(sds->obmat, velocity);
- normalize_v3(velocity);
- mul_v3_fl(velocity, vel_mag);
-
- /* use max value of fuel or smoke density */
- density = BLI_voxel_sample_trilinear(smoke_get_density(sds->fluid), sds->res, pos);
- if (smoke_has_fuel(sds->fluid)) {
- fuel = BLI_voxel_sample_trilinear(smoke_get_fuel(sds->fluid), sds->res, pos);
- }
- return MAX2(density, fuel);
- }
- return -1.0f;
-}
-
-int BKE_smoke_get_data_flags(SmokeDomainSettings *sds)
-{
- int flags = 0;
-
- if (sds->fluid) {
- if (smoke_has_heat(sds->fluid)) {
- flags |= SM_ACTIVE_HEAT;
- }
- if (smoke_has_fuel(sds->fluid)) {
- flags |= SM_ACTIVE_FIRE;
- }
- if (smoke_has_colors(sds->fluid)) {
- flags |= SM_ACTIVE_COLORS;
- }
- }
-
- return flags;
-}
-
-#endif /* WITH_SMOKE */
-
-bool BKE_smoke_show_highres(Scene *scene, SmokeDomainSettings *sds)
-{
- if ((sds->viewsettings & MOD_SMOKE_VIEW_SHOW_HIGHRES) == 0) {
- return false;
- }
- if (scene->r.mode & R_SIMPLIFY) {
- return !scene->r.simplify_smoke_ignore_highres;
- }
- return true;
-}
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index f2c0bf1e6f1..eb926c51ba9 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -406,6 +406,9 @@ GSet *BLI_gset_str_new(const char *info);
GSet *BLI_gset_pair_new_ex(const char *info, const unsigned int nentries_reserve)
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
GSet *BLI_gset_pair_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_int_new_ex(const char *info,
+ const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GSet *BLI_gset_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
/** \} */
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 05c3d43a0de..24346454a3f 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -19,7 +19,6 @@
#include <string.h> /* for memset() */
-struct Link;
struct ListBase;
/** \file
diff --git a/source/blender/blenlib/intern/BLI_ghash_utils.c b/source/blender/blenlib/intern/BLI_ghash_utils.c
index 1c6484acbdf..63559da5bd7 100644
--- a/source/blender/blenlib/intern/BLI_ghash_utils.c
+++ b/source/blender/blenlib/intern/BLI_ghash_utils.c
@@ -278,4 +278,13 @@ GSet *BLI_gset_pair_new(const char *info)
return BLI_gset_pair_new_ex(info, 0);
}
+GSet *BLI_gset_int_new_ex(const char *info, const uint nentries_reserve)
+{
+ return BLI_gset_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve);
+}
+GSet *BLI_gset_int_new(const char *info)
+{
+ return BLI_gset_int_new_ex(info, 0);
+}
+
/** \} */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9ec178f7a21..d433d38b557 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -83,7 +83,7 @@
#include "DNA_sdna_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_speaker_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
@@ -239,7 +239,7 @@
/* local prototypes */
static void read_libraries(FileData *basefd, ListBase *mainlist);
static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
-static void direct_link_modifiers(FileData *fd, ListBase *lb);
+static void direct_link_modifiers(FileData *fd, ListBase *lb, const Object *ob);
static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
@@ -4636,7 +4636,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
part->instance_object = newlibadr(fd, part->id.lib, part->instance_object);
part->instance_collection = newlibadr_us(fd, part->id.lib, part->instance_collection);
- part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
+ part->force_group = newlibadr(fd, part->id.lib, part->force_group);
part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
part->collision_group = newlibadr(fd, part->id.lib, part->collision_group);
@@ -4647,7 +4647,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group);
}
else {
- part->effector_weights = BKE_effector_add_weights(part->eff_group);
+ part->effector_weights = BKE_effector_add_weights(part->force_group);
}
if (part->instance_weights.first && part->instance_collection) {
@@ -4729,7 +4729,7 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
part->effector_weights = newdataadr(fd, part->effector_weights);
if (!part->effector_weights) {
- part->effector_weights = BKE_effector_add_weights(part->eff_group);
+ part->effector_weights = BKE_effector_add_weights(part->force_group);
}
link_list(fd, &part->instance_weights);
@@ -5372,12 +5372,12 @@ static void lib_link_object(FileData *fd, Main *main)
}
{
- SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob,
- eModifierType_Smoke);
+ FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob,
+ eModifierType_Fluid);
- if (smd && (smd->type == MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- /* Flag for refreshing the simulation after loading. */
- smd->domain->flags |= MOD_SMOKE_FILE_LOAD;
+ if (mmd && (mmd->type == MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
+ /* Flag for refreshing the simulation after loading */
+ mmd->domain->flags |= FLUID_DOMAIN_FILE_LOAD;
}
}
@@ -5485,7 +5485,7 @@ static void direct_link_pose(FileData *fd, bPose *pose)
}
}
-static void direct_link_modifiers(FileData *fd, ListBase *lb)
+static void direct_link_modifiers(FileData *fd, ListBase *lb, const Object *ob)
{
ModifierData *md;
@@ -5495,6 +5495,24 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
md->error = NULL;
md->runtime = NULL;
+ if (md->type == eModifierType_Fluidsim) {
+ blo_reportf_wrap(
+ fd->reports,
+ RPT_WARNING,
+ TIP_(
+ "Possible data loss when saving this file! %s modifier is deprecated (Object: %s)."),
+ md->name,
+ ob->id.name + 2);
+ }
+ else if (md->type == eModifierType_Smoke) {
+ blo_reportf_wrap(
+ fd->reports,
+ RPT_WARNING,
+ TIP_(
+ "Possible data loss when saving this file! %s modifier is deprecated (Object: %s)."),
+ md->name,
+ ob->id.name + 2);
+ }
/* if modifiers disappear, or for upward compatibility */
if (NULL == modifierType_getInfo(md->type)) {
md->type = eModifierType_None;
@@ -5537,91 +5555,82 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
clmd->solver_result = NULL;
}
- else if (md->type == eModifierType_Fluidsim) {
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
+ else if (md->type == eModifierType_Fluid) {
- fluidmd->fss = newdataadr(fd, fluidmd->fss);
- if (fluidmd->fss) {
- fluidmd->fss->fmd = fluidmd;
- fluidmd->fss->meshVelocities = NULL;
- }
- }
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
-
- if (smd->type == MOD_SMOKE_TYPE_DOMAIN) {
- smd->flow = NULL;
- smd->coll = NULL;
- smd->domain = newdataadr(fd, smd->domain);
- smd->domain->smd = smd;
-
- smd->domain->fluid = NULL;
- smd->domain->fluid_mutex = BLI_rw_mutex_alloc();
- smd->domain->wt = NULL;
- smd->domain->shadow = NULL;
- smd->domain->tex = NULL;
- smd->domain->tex_shadow = NULL;
- smd->domain->tex_flame = NULL;
- smd->domain->tex_flame_coba = NULL;
- smd->domain->tex_coba = NULL;
- smd->domain->tex_field = NULL;
- smd->domain->tex_velocity_x = NULL;
- smd->domain->tex_velocity_y = NULL;
- smd->domain->tex_velocity_z = NULL;
- smd->domain->tex_wt = NULL;
- smd->domain->coba = newdataadr(fd, smd->domain->coba);
-
- smd->domain->effector_weights = newdataadr(fd, smd->domain->effector_weights);
- if (!smd->domain->effector_weights) {
- smd->domain->effector_weights = BKE_effector_add_weights(NULL);
+ FluidModifierData *mmd = (FluidModifierData *)md;
+
+ if (mmd->type == MOD_FLUID_TYPE_DOMAIN) {
+ mmd->flow = NULL;
+ mmd->effector = NULL;
+ mmd->domain = newdataadr(fd, mmd->domain);
+ mmd->domain->mmd = mmd;
+
+ mmd->domain->fluid = NULL;
+ mmd->domain->fluid_mutex = BLI_rw_mutex_alloc();
+ mmd->domain->tex = NULL;
+ mmd->domain->tex_shadow = NULL;
+ mmd->domain->tex_flame = NULL;
+ mmd->domain->tex_flame_coba = NULL;
+ mmd->domain->tex_coba = NULL;
+ mmd->domain->tex_field = NULL;
+ mmd->domain->tex_velocity_x = NULL;
+ mmd->domain->tex_velocity_y = NULL;
+ mmd->domain->tex_velocity_z = NULL;
+ mmd->domain->tex_wt = NULL;
+ mmd->domain->mesh_velocities = NULL;
+ mmd->domain->coba = newdataadr(fd, mmd->domain->coba);
+
+ mmd->domain->effector_weights = newdataadr(fd, mmd->domain->effector_weights);
+ if (!mmd->domain->effector_weights) {
+ mmd->domain->effector_weights = BKE_effector_add_weights(NULL);
}
direct_link_pointcache_list(
- fd, &(smd->domain->ptcaches[0]), &(smd->domain->point_cache[0]), 1);
+ fd, &(mmd->domain->ptcaches[0]), &(mmd->domain->point_cache[0]), 1);
- /* Smoke uses only one cache from now on, so store pointer convert */
- if (smd->domain->ptcaches[1].first || smd->domain->point_cache[1]) {
- if (smd->domain->point_cache[1]) {
- PointCache *cache = newdataadr(fd, smd->domain->point_cache[1]);
+ /* Manta sim uses only one cache from now on, so store pointer convert */
+ if (mmd->domain->ptcaches[1].first || mmd->domain->point_cache[1]) {
+ if (mmd->domain->point_cache[1]) {
+ PointCache *cache = newdataadr(fd, mmd->domain->point_cache[1]);
if (cache->flag & PTCACHE_FAKE_SMOKE) {
- /* Smoke was already saved in "new format" and this cache is a fake one. */
+ /* Manta-sim/smoke was already saved in "new format" and this cache is a fake one. */
}
else {
printf(
- "High resolution smoke cache not available due to pointcache update. Please "
+ "High resolution manta cache not available due to pointcache update. Please "
"reset the simulation.\n");
}
BKE_ptcache_free(cache);
}
- BLI_listbase_clear(&smd->domain->ptcaches[1]);
- smd->domain->point_cache[1] = NULL;
- }
- }
- else if (smd->type == MOD_SMOKE_TYPE_FLOW) {
- smd->domain = NULL;
- smd->coll = NULL;
- smd->flow = newdataadr(fd, smd->flow);
- smd->flow->smd = smd;
- smd->flow->mesh = NULL;
- smd->flow->verts_old = NULL;
- smd->flow->numverts = 0;
- smd->flow->psys = newdataadr(fd, smd->flow->psys);
- }
- else if (smd->type == MOD_SMOKE_TYPE_COLL) {
- smd->flow = NULL;
- smd->domain = NULL;
- smd->coll = newdataadr(fd, smd->coll);
- if (smd->coll) {
- smd->coll->smd = smd;
- smd->coll->verts_old = NULL;
- smd->coll->numverts = 0;
- smd->coll->mesh = NULL;
+ BLI_listbase_clear(&mmd->domain->ptcaches[1]);
+ mmd->domain->point_cache[1] = NULL;
+ }
+ }
+ else if (mmd->type == MOD_FLUID_TYPE_FLOW) {
+ mmd->domain = NULL;
+ mmd->effector = NULL;
+ mmd->flow = newdataadr(fd, mmd->flow);
+ mmd->flow->mmd = mmd;
+ mmd->flow->mesh = NULL;
+ mmd->flow->verts_old = NULL;
+ mmd->flow->numverts = 0;
+ mmd->flow->psys = newdataadr(fd, mmd->flow->psys);
+ }
+ else if (mmd->type == MOD_FLUID_TYPE_EFFEC) {
+ mmd->flow = NULL;
+ mmd->domain = NULL;
+ mmd->effector = newdataadr(fd, mmd->effector);
+ if (mmd->effector) {
+ mmd->effector->mmd = mmd;
+ mmd->effector->verts_old = NULL;
+ mmd->effector->numverts = 0;
+ mmd->effector->mesh = NULL;
}
else {
- smd->type = 0;
- smd->flow = NULL;
- smd->domain = NULL;
- smd->coll = NULL;
+ mmd->type = 0;
+ mmd->flow = NULL;
+ mmd->domain = NULL;
+ mmd->effector = NULL;
}
}
}
@@ -5968,7 +5977,7 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->matbits = newdataadr(fd, ob->matbits);
/* do it here, below old data gets converted */
- direct_link_modifiers(fd, &ob->modifiers);
+ direct_link_modifiers(fd, &ob->modifiers, ob);
direct_link_gpencil_modifiers(fd, &ob->greasepencil_modifiers);
direct_link_shaderfxs(fd, &ob->shader_fx);
@@ -10407,7 +10416,7 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
expand_doit(fd, mainvar, part->instance_object);
expand_doit(fd, mainvar, part->instance_collection);
- expand_doit(fd, mainvar, part->eff_group);
+ expand_doit(fd, mainvar, part->force_group);
expand_doit(fd, mainvar, part->bb_ob);
expand_doit(fd, mainvar, part->collision_group);
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 3e7b1582603..a5ab0c0acb7 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -50,7 +50,7 @@
#include "DNA_screen_types.h"
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_world_types.h"
@@ -1789,19 +1789,19 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
ModifierData *md;
for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
+ if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- smd->domain->vorticity = 2.0f;
- smd->domain->time_scale = 1.0f;
+ if ((mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
+ mmd->domain->vorticity = 2.0f;
+ mmd->domain->time_scale = 1.0f;
- if (!(smd->domain->flags & (1 << 4))) {
+ if (!(mmd->domain->flags & (1 << 4))) {
continue;
}
/* delete old MOD_SMOKE_INITVELOCITY flag */
- smd->domain->flags &= ~(1 << 4);
+ mmd->domain->flags &= ~(1 << 4);
/* for now just add it to all flow objects in the scene */
{
@@ -1809,19 +1809,19 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
for (ob2 = bmain->objects.first; ob2; ob2 = ob2->id.next) {
ModifierData *md2;
for (md2 = ob2->modifiers.first; md2; md2 = md2->next) {
- if (md2->type == eModifierType_Smoke) {
- SmokeModifierData *smd2 = (SmokeModifierData *)md2;
+ if (md2->type == eModifierType_Fluid) {
+ FluidModifierData *mmd2 = (FluidModifierData *)md2;
- if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) {
- smd2->flow->flags |= MOD_SMOKE_FLOW_INITVELOCITY;
+ if ((mmd2->type & MOD_FLUID_TYPE_FLOW) && mmd2->flow) {
+ mmd2->flow->flags |= FLUID_FLOW_INITVELOCITY;
}
}
}
}
}
}
- else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
- smd->flow->vel_multi = 1.0f;
+ else if ((mmd->type & MOD_FLUID_TYPE_FLOW) && mmd->flow) {
+ mmd->flow->vel_multi = 1.0f;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 40219a36323..f23e4b5e2a4 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -39,7 +39,7 @@
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
#include "DNA_sdna_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_space_types.h"
#include "DNA_world_types.h"
#include "DNA_light_types.h"
@@ -1292,12 +1292,12 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
ModifierData *md;
for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- int maxres = max_iii(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
- smd->domain->scale = smd->domain->dx * maxres;
- smd->domain->dx = 1.0f / smd->domain->scale;
+ if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if ((mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
+ int maxres = max_iii(mmd->domain->res[0], mmd->domain->res[1], mmd->domain->res[2]);
+ mmd->domain->scale = mmd->domain->dx * maxres;
+ mmd->domain->dx = 1.0f / mmd->domain->scale;
}
}
}
@@ -1610,31 +1610,31 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
ModifierData *md;
for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
+ if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if ((mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
/* keep branch saves if possible */
- if (!smd->domain->flame_max_temp) {
- smd->domain->burning_rate = 0.75f;
- smd->domain->flame_smoke = 1.0f;
- smd->domain->flame_vorticity = 0.5f;
- smd->domain->flame_ignition = 1.25f;
- smd->domain->flame_max_temp = 1.75f;
- smd->domain->adapt_threshold = 0.02f;
- smd->domain->adapt_margin = 4;
- smd->domain->flame_smoke_color[0] = 0.7f;
- smd->domain->flame_smoke_color[1] = 0.7f;
- smd->domain->flame_smoke_color[2] = 0.7f;
+ if (!mmd->domain->flame_max_temp) {
+ mmd->domain->burning_rate = 0.75f;
+ mmd->domain->flame_smoke = 1.0f;
+ mmd->domain->flame_vorticity = 0.5f;
+ mmd->domain->flame_ignition = 1.25f;
+ mmd->domain->flame_max_temp = 1.75f;
+ mmd->domain->adapt_threshold = 0.02f;
+ mmd->domain->adapt_margin = 4;
+ mmd->domain->flame_smoke_color[0] = 0.7f;
+ mmd->domain->flame_smoke_color[1] = 0.7f;
+ mmd->domain->flame_smoke_color[2] = 0.7f;
}
}
- else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
- if (!smd->flow->texture_size) {
- smd->flow->fuel_amount = 1.0;
- smd->flow->surface_distance = 1.5;
- smd->flow->color[0] = 0.7f;
- smd->flow->color[1] = 0.7f;
- smd->flow->color[2] = 0.7f;
- smd->flow->texture_size = 1.0f;
+ else if ((mmd->type & MOD_FLUID_TYPE_FLOW) && mmd->flow) {
+ if (!mmd->flow->texture_size) {
+ mmd->flow->fuel_amount = 1.0;
+ mmd->flow->surface_distance = 1.5;
+ mmd->flow->color[0] = 0.7f;
+ mmd->flow->color[1] = 0.7f;
+ mmd->flow->color[2] = 0.7f;
+ mmd->flow->texture_size = 1.0f;
}
}
}
@@ -2140,14 +2140,14 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
ModifierData *md;
for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- if (smd->domain->flags & MOD_SMOKE_HIGH_SMOOTH) {
- smd->domain->highres_sampling = SM_HRES_LINEAR;
+ if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if ((mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
+ if (mmd->domain->flags & FLUID_DOMAIN_USE_HIGH_SMOOTH) {
+ mmd->domain->highres_sampling = SM_HRES_LINEAR;
}
else {
- smd->domain->highres_sampling = SM_HRES_NEAREST;
+ mmd->domain->highres_sampling = SM_HRES_NEAREST;
}
}
}
@@ -2207,11 +2207,11 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
ModifierData *md;
for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
- if (!smd->flow->particle_size) {
- smd->flow->particle_size = 1.0f;
+ if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if ((mmd->type & MOD_FLUID_TYPE_FLOW) && mmd->flow) {
+ if (!mmd->flow->particle_size) {
+ mmd->flow->particle_size = 1.0f;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index fb570b956b6..f421f31814c 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -46,7 +46,7 @@
#include "DNA_particle_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_light_types.h"
@@ -1549,18 +1549,18 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- if (!DNA_struct_elem_find(fd->filesdna, "SmokeModifierData", "float", "slice_per_voxel")) {
+ if (!DNA_struct_elem_find(fd->filesdna, "FluidModifierData", "float", "slice_per_voxel")) {
Object *ob;
ModifierData *md;
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->domain) {
- smd->domain->slice_per_voxel = 5.0f;
- smd->domain->slice_depth = 0.5f;
- smd->domain->display_thickness = 1.0f;
+ if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if (mmd->domain) {
+ mmd->domain->slice_per_voxel = 5.0f;
+ mmd->domain->slice_depth = 0.5f;
+ mmd->domain->display_thickness = 1.0f;
}
}
}
@@ -1719,16 +1719,16 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
if (!MAIN_VERSION_ATLEAST(bmain, 279, 3)) {
- if (!DNA_struct_elem_find(fd->filesdna, "SmokeDomainSettings", "float", "clipping")) {
+ if (!DNA_struct_elem_find(fd->filesdna, "FluidDomainSettings", "float", "clipping")) {
Object *ob;
ModifierData *md;
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->domain) {
- smd->domain->clipping = 1e-3f;
+ if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if (mmd->domain) {
+ mmd->domain->clipping = 1e-3f;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 5d46f0735eb..73cdd40c02c 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -2292,7 +2292,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
part->omat = paf->mat[0];
part->hair_step = paf->totkey;
- part->eff_group = paf->group;
+ part->force_group = paf->group;
/* old system didn't interpolate between keypoints at render time */
part->draw_step = part->ren_step = 0;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 2b68ba2a8f6..89c097044f4 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -126,7 +126,7 @@
#include "DNA_scene_types.h"
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_speaker_types.h"
@@ -1628,38 +1628,38 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
writestruct(wd, DATA, EffectorWeights, 1, clmd->sim_parms->effector_weights);
write_pointcaches(wd, &clmd->ptcaches);
}
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
+ else if (md->type == eModifierType_Fluid) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ writestruct(wd, DATA, FluidDomainSettings, 1, mmd->domain);
- if (smd->domain) {
- write_pointcaches(wd, &(smd->domain->ptcaches[0]));
+ if (mmd->domain) {
+ write_pointcaches(wd, &(mmd->domain->ptcaches[0]));
/* create fake pointcache so that old blender versions can read it */
- smd->domain->point_cache[1] = BKE_ptcache_add(&smd->domain->ptcaches[1]);
- smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE | PTCACHE_FAKE_SMOKE;
- smd->domain->point_cache[1]->step = 1;
+ mmd->domain->point_cache[1] = BKE_ptcache_add(&mmd->domain->ptcaches[1]);
+ mmd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE | PTCACHE_FAKE_SMOKE;
+ mmd->domain->point_cache[1]->step = 1;
- write_pointcaches(wd, &(smd->domain->ptcaches[1]));
+ write_pointcaches(wd, &(mmd->domain->ptcaches[1]));
- if (smd->domain->coba) {
- writestruct(wd, DATA, ColorBand, 1, smd->domain->coba);
+ if (mmd->domain->coba) {
+ writestruct(wd, DATA, ColorBand, 1, mmd->domain->coba);
}
/* cleanup the fake pointcache */
- BKE_ptcache_free_list(&smd->domain->ptcaches[1]);
- smd->domain->point_cache[1] = NULL;
+ BKE_ptcache_free_list(&mmd->domain->ptcaches[1]);
+ mmd->domain->point_cache[1] = NULL;
- writestruct(wd, DATA, EffectorWeights, 1, smd->domain->effector_weights);
+ writestruct(wd, DATA, EffectorWeights, 1, mmd->domain->effector_weights);
}
}
- else if (smd->type & MOD_SMOKE_TYPE_FLOW) {
- writestruct(wd, DATA, SmokeFlowSettings, 1, smd->flow);
+ else if (mmd->type & MOD_FLUID_TYPE_FLOW) {
+ writestruct(wd, DATA, FluidFlowSettings, 1, mmd->flow);
}
- else if (smd->type & MOD_SMOKE_TYPE_COLL) {
- writestruct(wd, DATA, SmokeCollSettings, 1, smd->coll);
+ else if (mmd->type & MOD_FLUID_TYPE_EFFEC) {
+ writestruct(wd, DATA, FluidEffectorSettings, 1, mmd->effector);
}
}
else if (md->type == eModifierType_Fluidsim) {
diff --git a/source/blender/collada/ExtraTags.h b/source/blender/collada/ExtraTags.h
index 2d827159af8..9191182c757 100644
--- a/source/blender/collada/ExtraTags.h
+++ b/source/blender/collada/ExtraTags.h
@@ -18,6 +18,9 @@
* \ingroup collada
*/
+#ifndef __EXTRATAGS_H__
+#define __EXTRATAGS_H__
+
#include <string>
#include <map>
#include <vector>
@@ -70,3 +73,5 @@ class ExtraTags {
/** Get text data for tag as a string. */
std::string asString(std::string tag, bool *ok);
};
+
+#endif /* __EXTRATAGS_H__ */
diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.cpp b/source/blender/compositor/nodes/COM_DenoiseNode.cpp
index 7de120d1204..a18fc82908a 100644
--- a/source/blender/compositor/nodes/COM_DenoiseNode.cpp
+++ b/source/blender/compositor/nodes/COM_DenoiseNode.cpp
@@ -1,6 +1,4 @@
/*
- * Copyright 2019, Blender Foundation.
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -15,10 +13,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Stefan Werner
+ * Copyright 2019, Blender Foundation.
*/
-
#include "COM_DenoiseNode.h"
#include "DNA_node_types.h"
#include "COM_SetValueOperation.h"
diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.h b/source/blender/compositor/nodes/COM_DenoiseNode.h
index 0924da8931c..6cbe598f7d2 100644
--- a/source/blender/compositor/nodes/COM_DenoiseNode.h
+++ b/source/blender/compositor/nodes/COM_DenoiseNode.h
@@ -1,6 +1,4 @@
/*
- * Copyright 2019, Blender Foundation.
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -15,8 +13,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Stefan Werner
+ * Copyright 2019, Blender Foundation.
*/
#ifndef __COM_DENOISENODE_H__
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.cpp b/source/blender/compositor/operations/COM_DenoiseOperation.cpp
index 8235c296c5a..d9a59002caf 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.cpp
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.cpp
@@ -1,6 +1,4 @@
/*
- * Copyright 2019, Blender Foundation.
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -15,8 +13,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Stefan Werner
+ * Copyright 2019, Blender Foundation.
*/
#include "COM_DenoiseOperation.h"
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.h b/source/blender/compositor/operations/COM_DenoiseOperation.h
index fc06bb81a97..6a53eead65c 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.h
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.h
@@ -1,6 +1,4 @@
/*
- * Copyright 2019, Blender Foundation.
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -15,8 +13,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Stefan Werner
+ * Copyright 2019, Blender Foundation.
*/
#ifndef __COM_DENOISEOPERATION_H__
diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc
index 3f81e49b170..f47081cd54e 100644
--- a/source/blender/depsgraph/intern/depsgraph_physics.cc
+++ b/source/blender/depsgraph/intern/depsgraph_physics.cc
@@ -54,7 +54,7 @@ static ePhysicsRelationType modifier_to_relation_type(unsigned int modifier_type
switch (modifier_type) {
case eModifierType_Collision:
return DEG_PHYSICS_COLLISION;
- case eModifierType_Smoke:
+ case eModifierType_Fluid:
return DEG_PHYSICS_SMOKE_COLLISION;
case eModifierType_DynamicPaint:
return DEG_PHYSICS_DYNAMIC_BRUSH;
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h
index a9d528a254c..427e9c7b483 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h
@@ -23,9 +23,9 @@
#pragma once
-struct anim;
struct MovieClip;
struct MovieClipCache;
+struct anim;
namespace DEG {
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 723965172ae..6c55fa7ce30 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -121,10 +121,10 @@ set(SRC
engines/select/select_engine.c
engines/overlay/overlay_antialiasing.c
engines/overlay/overlay_armature.c
- engines/overlay/overlay_engine.c
engines/overlay/overlay_edit_curve.c
- engines/overlay/overlay_edit_text.c
engines/overlay/overlay_edit_mesh.c
+ engines/overlay/overlay_edit_text.c
+ engines/overlay/overlay_engine.c
engines/overlay/overlay_extra.c
engines/overlay/overlay_facing.c
engines/overlay/overlay_grid.c
@@ -135,8 +135,8 @@ set(SRC
engines/overlay/overlay_outline.c
engines/overlay/overlay_paint.c
engines/overlay/overlay_particle.c
- engines/overlay/overlay_shader.c
engines/overlay/overlay_sculpt.c
+ engines/overlay/overlay_shader.c
engines/overlay/overlay_wireframe.c
DRW_engine.h
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 67fd441a0b1..d32f93432b8 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -28,12 +28,12 @@
#include "BLI_string_utils.h"
#include "DNA_object_force_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_world_types.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
-#include "BKE_smoke.h"
+#include "BKE_fluid.h"
#include "ED_screen.h"
@@ -63,7 +63,7 @@ static struct {
GPUTexture *dummy_scatter;
GPUTexture *dummy_transmit;
- /* List of all smoke domains rendered within this frame. */
+ /* List of all fluid simulation / smoke domains rendered within this frame. */
ListBase smoke_domains;
} e_data = {NULL}; /* Engine data */
@@ -390,8 +390,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
Scene *scene,
Object *ob)
{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- static float white[3] = {1.0f, 1.0f, 1.0f};
+ static const float white[3] = {1.0f, 1.0f, 1.0f};
float *texcoloc = NULL;
float *texcosize = NULL;
@@ -430,41 +429,49 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
/* Smoke Simulation */
if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
- (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (md = modifiers_findByType(ob, eModifierType_Fluid)) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
- ((SmokeModifierData *)md)->domain != NULL) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- SmokeDomainSettings *sds = smd->domain;
+ ((FluidModifierData *)md)->domain != NULL) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ FluidDomainSettings *mds = mmd->domain;
+
+ /* Don't try to show liquid domains here. */
+ if (!mds->fluid || !(mds->type == FLUID_DOMAIN_TYPE_GAS)) {
+ return;
+ }
/* Don't show smoke before simulation starts, this could be made an option in the future. */
+ /* (sebbas): Always show smoke for manta */
+#if 0
+ const DRWContextState *draw_ctx = DRW_context_state_get();
const bool show_smoke = ((int)DEG_get_ctime(draw_ctx->depsgraph) >=
- sds->point_cache[0]->startframe);
+ *mds->point_cache[0]->startframe);
+#endif
- if (sds->fluid && show_smoke) {
- const bool show_highres = BKE_smoke_show_highres(scene, sds);
- if (!sds->wt || !show_highres) {
- GPU_create_smoke(smd, 0);
+ if (mds->fluid && (mds->type == FLUID_DOMAIN_TYPE_GAS) /* && show_smoke */) {
+ if (!(mds->flags & FLUID_DOMAIN_USE_NOISE)) {
+ GPU_create_smoke(mmd, 0);
}
- else if (sds->wt && show_highres) {
- GPU_create_smoke(smd, 1);
+ else if (mds->flags & FLUID_DOMAIN_USE_NOISE) {
+ GPU_create_smoke(mmd, 1);
}
- BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd));
+ BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(mmd));
}
DRW_shgroup_uniform_texture_ref(
- grp, "sampdensity", sds->tex ? &sds->tex : &e_data.dummy_density);
+ grp, "sampdensity", mds->tex ? &mds->tex : &e_data.dummy_density);
DRW_shgroup_uniform_texture_ref(
- grp, "sampflame", sds->tex_flame ? &sds->tex_flame : &e_data.dummy_flame);
+ grp, "sampflame", mds->tex_flame ? &mds->tex_flame : &e_data.dummy_flame);
/* Constant Volume color. */
- bool use_constant_color = ((sds->active_fields & SM_ACTIVE_COLORS) == 0 &&
- (sds->active_fields & SM_ACTIVE_COLOR_SET) != 0);
+ bool use_constant_color = ((mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
+ (mds->active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET) != 0);
DRW_shgroup_uniform_vec3(
- grp, "volumeColor", (use_constant_color) ? sds->active_color : white, 1);
+ grp, "volumeColor", (use_constant_color) ? mds->active_color : white, 1);
/* Output is such that 0..1 maps to 0..1000K */
- DRW_shgroup_uniform_vec2(grp, "unftemperature", &sds->flame_ignition, 1);
+ DRW_shgroup_uniform_vec2(grp, "unftemperature", &mds->flame_ignition, 1);
}
else {
DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
@@ -692,8 +699,8 @@ void EEVEE_volumes_free_smoke_textures(void)
{
/* Free Smoke Textures after rendering */
for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) {
- SmokeModifierData *smd = (SmokeModifierData *)link->data;
- GPU_free_smoke(smd);
+ FluidModifierData *mmd = (FluidModifierData *)link->data;
+ GPU_free_smoke(mmd);
}
BLI_freelistN(&e_data.smoke_domains);
}
diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl
index 5a738d0f130..35bfb411cb9 100644
--- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl
@@ -61,4 +61,4 @@ void main()
else {
fragColor = vec4(1.0, 0.0, 1.0, 1.0);
}
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index 7e75edfddf3..4c6ce896ebc 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -1948,9 +1948,12 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
bGPdata *gpd = (bGPdata *)ob->data;
- const bool main_onion = stl->storage->is_main_onion;
+ /* If render mode, instead to use view switches, test if the datablock has
+ * the onion activated for render. */
+ const bool render_onion = (gpd && gpd->onion_flag & GP_ONION_GHOST_ALWAYS);
+ const bool main_onion = (stl->storage->is_render) ? render_onion : stl->storage->is_main_onion;
+ const bool overlay = (stl->storage->is_render) ? render_onion : stl->storage->is_main_overlay;
const bool playing = stl->storage->is_playing;
- const bool overlay = stl->storage->is_main_overlay;
const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay &&
main_onion && !playing && gpencil_onion_active(gpd);
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index b0fb95380f4..0b77fcad265 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -2354,4 +2354,4 @@ void OVERLAY_pose_draw(OVERLAY_Data *vedata)
DRW_draw_pass(psl->armature_ps[1]);
}
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/overlay_edit_curve.c b/source/blender/draw/engines/overlay/overlay_edit_curve.c
index b39dc39fd47..d9b9fac6b4b 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_curve.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_curve.c
@@ -129,4 +129,4 @@ void OVERLAY_edit_curve_draw(OVERLAY_Data *vedata)
DRW_draw_pass(psl->edit_curve_wire_ps[1]);
DRW_draw_pass(psl->edit_curve_handle_ps);
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/overlay_edit_text.c b/source/blender/draw/engines/overlay/overlay_edit_text.c
index 0975608a300..72b5ae74255 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_text.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_text.c
@@ -202,4 +202,4 @@ void OVERLAY_edit_text_draw(OVERLAY_Data *vedata)
DRW_draw_pass(psl->edit_text_wire_ps[1]);
DRW_draw_pass(psl->edit_text_overlay_ps);
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index f6e3ed4d4de..90ddb9f7476 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -45,7 +45,7 @@
#include "DNA_modifier_types.h"
#include "DNA_object_force_types.h"
#include "DNA_rigidbody_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DEG_depsgraph_query.h"
@@ -1410,22 +1410,22 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
Scene *scene,
float *color)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
- SmokeDomainSettings *sds = smd->domain;
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ FluidDomainSettings *mds = mmd->domain;
/* Don't show smoke before simulation starts, this could be made an option in the future. */
- const bool draw_velocity = (sds->draw_velocity && sds->fluid &&
- CFRA >= sds->point_cache[0]->startframe);
+ const bool draw_velocity = (mds->draw_velocity && mds->fluid &&
+ CFRA >= mds->point_cache[0]->startframe);
/* Small cube showing voxel size. */
{
float min[3];
- madd_v3fl_v3fl_v3fl_v3i(min, sds->p0, sds->cell_size, sds->res_min);
+ madd_v3fl_v3fl_v3fl_v3i(min, mds->p0, mds->cell_size, mds->res_min);
float voxel_cubemat[4][4] = {{0.0f}};
/* scale small cube to voxel size */
- voxel_cubemat[0][0] = 1.0f / (float)sds->base_res[0];
- voxel_cubemat[1][1] = 1.0f / (float)sds->base_res[1];
- voxel_cubemat[2][2] = 1.0f / (float)sds->base_res[2];
+ voxel_cubemat[0][0] = 1.0f / (float)mds->base_res[0];
+ voxel_cubemat[1][1] = 1.0f / (float)mds->base_res[1];
+ voxel_cubemat[2][2] = 1.0f / (float)mds->base_res[2];
voxel_cubemat[3][3] = 1.0f;
/* translate small cube to corner */
copy_v3_v3(voxel_cubemat[3], min);
@@ -1437,38 +1437,38 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
}
if (draw_velocity) {
- const bool use_needle = (sds->vector_draw_type == VECTOR_DRAW_NEEDLE);
+ const bool use_needle = (mds->vector_draw_type == VECTOR_DRAW_NEEDLE);
int line_count = (use_needle) ? 6 : 1;
int slice_axis = -1;
- line_count *= sds->res[0] * sds->res[1] * sds->res[2];
+ line_count *= mds->res[0] * mds->res[1] * mds->res[2];
- if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED &&
- sds->axis_slice_method == AXIS_SLICE_SINGLE) {
+ if (mds->slice_method == FLUID_DOMAIN_SLICE_AXIS_ALIGNED &&
+ mds->axis_slice_method == AXIS_SLICE_SINGLE) {
float viewinv[4][4];
DRW_view_viewmat_get(NULL, viewinv, true);
- const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewinv[2]) :
- sds->slice_axis - 1;
+ const int axis = (mds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewinv[2]) :
+ mds->slice_axis - 1;
slice_axis = axis;
- line_count /= sds->res[axis];
+ line_count /= mds->res[axis];
}
- GPU_create_smoke_velocity(smd);
+ GPU_create_smoke_velocity(mmd);
GPUShader *sh = OVERLAY_shader_volume_velocity(use_needle);
DRWShadingGroup *grp = DRW_shgroup_create(sh, data->psl->extra_ps[0]);
- DRW_shgroup_uniform_texture(grp, "velocityX", sds->tex_velocity_x);
- DRW_shgroup_uniform_texture(grp, "velocityY", sds->tex_velocity_y);
- DRW_shgroup_uniform_texture(grp, "velocityZ", sds->tex_velocity_z);
- DRW_shgroup_uniform_float_copy(grp, "displaySize", sds->vector_scale);
- DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth);
- DRW_shgroup_uniform_vec3_copy(grp, "cellSize", sds->cell_size);
- DRW_shgroup_uniform_vec3_copy(grp, "domainOriginOffset", sds->p0);
- DRW_shgroup_uniform_ivec3_copy(grp, "adaptiveCellOffset", sds->res_min);
+ DRW_shgroup_uniform_texture(grp, "velocityX", mds->tex_velocity_x);
+ DRW_shgroup_uniform_texture(grp, "velocityY", mds->tex_velocity_y);
+ DRW_shgroup_uniform_texture(grp, "velocityZ", mds->tex_velocity_z);
+ DRW_shgroup_uniform_float_copy(grp, "displaySize", mds->vector_scale);
+ DRW_shgroup_uniform_float_copy(grp, "slicePosition", mds->slice_depth);
+ DRW_shgroup_uniform_vec3_copy(grp, "cellSize", mds->cell_size);
+ DRW_shgroup_uniform_vec3_copy(grp, "domainOriginOffset", mds->p0);
+ DRW_shgroup_uniform_ivec3_copy(grp, "adaptiveCellOffset", mds->res_min);
DRW_shgroup_uniform_int_copy(grp, "sliceAxis", slice_axis);
DRW_shgroup_call_procedural_lines(grp, ob, line_count);
- BLI_addtail(&data->stl->pd->smoke_domains, BLI_genericNodeN(smd));
+ BLI_addtail(&data->stl->pd->smoke_domains, BLI_genericNodeN(mmd));
}
}
@@ -1482,8 +1482,8 @@ static void OVERLAY_volume_free_smoke_textures(OVERLAY_Data *data)
* all viewport in a redraw at least. */
LinkData *link;
while ((link = BLI_pophead(&data->stl->pd->smoke_domains))) {
- SmokeModifierData *smd = (SmokeModifierData *)link->data;
- GPU_free_smoke_velocity(smd);
+ FluidModifierData *mmd = (FluidModifierData *)link->data;
+ GPU_free_smoke_velocity(mmd);
MEM_freeN(link);
}
}
@@ -1555,9 +1555,9 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob)
const bool draw_xform = draw_ctx->object_mode == OB_MODE_OBJECT &&
(scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) &&
(ob->base_flag & BASE_SELECTED) && !is_select_mode;
- const bool draw_volume = !from_dupli && (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ const bool draw_volume = !from_dupli && (md = modifiers_findByType(ob, eModifierType_Fluid)) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
- (((SmokeModifierData *)md)->domain != NULL);
+ (((FluidModifierData *)md)->domain != NULL);
float *color;
int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color);
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 9be92e0ab14..996ee845799 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -571,4 +571,4 @@ OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void);
void OVERLAY_shader_free(void);
-#endif /* __OVERLAY_PRIVATE_H__ */ \ No newline at end of file
+#endif /* __OVERLAY_PRIVATE_H__ */
diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
index 386e6d9e141..4784d420e1d 100644
--- a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
@@ -147,4 +147,4 @@ void main()
fragColor = mix(fragColor, fragColor / fragColor.a, blend);
}
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl
index 4f3c36c7bd7..8cf8ba121ed 100644
--- a/source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/antialiasing_vert.glsl
@@ -8,4 +8,4 @@ void main()
float y = float((v & 2) << 1);
gl_Position = vec4(x - 1.0, y - 1.0, 1.0, 1.0);
uvs = vec2(x, y) * 0.5;
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_frag.glsl b/source/blender/draw/engines/overlay/shaders/extra_frag.glsl
index 8a8ae8a9611..a2572f44e70 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_frag.glsl
@@ -10,4 +10,4 @@ void main()
{
fragColor = finalColor;
lineOutput = pack_line_data(gl_FragCoord.xy, edgeStart, edgePos);
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_groundline_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_groundline_vert.glsl
index 4b08ea587d4..738f0025f07 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_groundline_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_groundline_vert.glsl
@@ -27,4 +27,4 @@ void main()
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_loose_point_frag.glsl b/source/blender/draw/engines/overlay/shaders/extra_loose_point_frag.glsl
index 8784b6cd73a..c27061f8f97 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_loose_point_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_loose_point_frag.glsl
@@ -15,4 +15,4 @@ void main()
* the depth and creating mini-spheres.
* Disabled as it has performance impact. */
// gl_FragDepth = gl_FragCoord.z + 1e-6 * fac;
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_loose_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_loose_point_vert.glsl
index 76a2678a50e..7e31bf966bc 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_loose_point_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_loose_point_vert.glsl
@@ -17,4 +17,4 @@ void main()
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_point_vert.glsl
index 14c03248981..537c55cf3f5 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_point_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_point_vert.glsl
@@ -27,4 +27,4 @@ void main()
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
index a72c5adb691..92db27ea6dd 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_vert.glsl
@@ -224,4 +224,4 @@ void main()
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_wire_frag.glsl b/source/blender/draw/engines/overlay/shaders/extra_wire_frag.glsl
index 7e469aee18d..a2bc13ba443 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_wire_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_wire_frag.glsl
@@ -28,4 +28,4 @@ void main()
if (fract(dist / dash_width) > dash_factor) {
discard;
}
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
index 933b9d65a5f..97183638a71 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl
@@ -37,4 +37,4 @@ void main()
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
index 64f88bd74fa..752694301f7 100644
--- a/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/volume_velocity_vert.glsl
@@ -6,11 +6,11 @@ uniform float displaySize = 1.0;
uniform float slicePosition;
uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
-/* SmokeDomainSettings.cell_size */
+/* FluidDomainSettings.cell_size */
uniform vec3 cellSize;
-/* SmokeDomainSettings.p0 */
+/* FluidDomainSettings.p0 */
uniform vec3 domainOriginOffset;
-/* SmokeDomainSettings.res_min */
+/* FluidDomainSettings.res_min */
uniform ivec3 adaptiveCellOffset;
flat out vec4 finalColor;
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 8e61750da38..a536132a1cf 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -34,6 +34,7 @@
#include "BKE_particle.h"
#include "DNA_image_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
@@ -981,9 +982,10 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
ModifierData *md;
if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
- (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (md = modifiers_findByType(ob, eModifierType_Fluid)) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
- (((SmokeModifierData *)md)->domain != NULL)) {
+ (((FluidModifierData *)md)->domain != NULL) &&
+ (((FluidModifierData *)md)->domain->type == FLUID_DOMAIN_TYPE_GAS)) {
workbench_volume_cache_populate(vedata, scene, ob, md);
return; /* Do not draw solid in this case. */
}
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index dbd7ebfe0d1..90f5d24fabd 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -33,6 +33,7 @@
#include "BKE_particle.h"
#include "DNA_image_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
@@ -618,9 +619,10 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
ModifierData *md;
if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
- (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (md = modifiers_findByType(ob, eModifierType_Fluid)) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
- (((SmokeModifierData *)md)->domain != NULL)) {
+ (((FluidModifierData *)md)->domain != NULL) &&
+ (((FluidModifierData *)md)->domain->type == FLUID_DOMAIN_TYPE_GAS)) {
workbench_volume_cache_populate(vedata, scene, ob, md);
return; /* Do not draw solid in this case. */
}
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index 23f0898c138..2f7296fb40f 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -23,7 +23,7 @@
#include "workbench_private.h"
#include "BKE_object.h"
-#include "BKE_smoke.h"
+#include "BKE_fluid.h"
#include "BLI_rand.h"
#include "BLI_dynstr.h"
@@ -31,7 +31,7 @@
#include "DNA_modifier_types.h"
#include "DNA_object_force_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "GPU_draw.h"
@@ -119,57 +119,56 @@ void workbench_volume_cache_init(WORKBENCH_Data *vedata)
}
void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
- Scene *scene,
+ Scene *UNUSED(scene),
Object *ob,
ModifierData *md)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
- SmokeDomainSettings *sds = smd->domain;
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ FluidDomainSettings *mds = mmd->domain;
WORKBENCH_PrivateData *wpd = vedata->stl->g_data;
WORKBENCH_EffectInfo *effect_info = vedata->stl->effects;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRWShadingGroup *grp = NULL;
- /* Don't show smoke before simulation starts, this could be made an option in the future. */
- if (!sds->fluid || CFRA < sds->point_cache[0]->startframe) {
+ /* Don't try to show liquid domains here */
+ if (!mds->fluid || !(mds->type == FLUID_DOMAIN_TYPE_GAS)) {
return;
}
wpd->volumes_do = true;
- const bool show_highres = BKE_smoke_show_highres(scene, sds);
- if (sds->use_coba) {
- GPU_create_smoke_coba_field(smd);
+ if (mds->use_coba) {
+ GPU_create_smoke_coba_field(mmd);
}
- else if (!sds->wt || !show_highres) {
- GPU_create_smoke(smd, 0);
+ else if (!(mds->flags & FLUID_DOMAIN_USE_NOISE)) {
+ GPU_create_smoke(mmd, 0);
}
- else if (sds->wt && show_highres) {
- GPU_create_smoke(smd, 1);
+ else if (mds->flags & FLUID_DOMAIN_USE_NOISE) {
+ GPU_create_smoke(mmd, 1);
}
- if ((!sds->use_coba && sds->tex == NULL) || (sds->use_coba && sds->tex_field == NULL)) {
+ if ((!mds->use_coba && mds->tex == NULL) || (mds->use_coba && mds->tex_field == NULL)) {
return;
}
- const bool use_slice = (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED &&
- sds->axis_slice_method == AXIS_SLICE_SINGLE);
- const bool cubic_interp = (sds->interp_method == VOLUME_INTERP_CUBIC);
- GPUShader *sh = volume_shader_get(use_slice, sds->use_coba, cubic_interp);
+ const bool use_slice = (mds->slice_method == FLUID_DOMAIN_SLICE_AXIS_ALIGNED &&
+ mds->axis_slice_method == AXIS_SLICE_SINGLE);
+ const bool cubic_interp = (mds->interp_method == VOLUME_INTERP_CUBIC);
+ GPUShader *sh = volume_shader_get(use_slice, mds->use_coba, cubic_interp);
if (use_slice) {
float invviewmat[4][4];
DRW_view_viewmat_get(NULL, invviewmat, true);
- const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ?
+ const int axis = (mds->slice_axis == SLICE_AXIS_AUTO) ?
axis_dominant_v3_single(invviewmat[2]) :
- sds->slice_axis - 1;
+ mds->slice_axis - 1;
float dim[3];
BKE_object_dimensions_get(ob, dim);
/* 0.05f to achieve somewhat the same opacity as the full view. */
float step_length = max_ff(1e-16f, dim[axis] * 0.05f);
grp = DRW_shgroup_create(sh, vedata->psl->volume_pass);
- DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth);
+ DRW_shgroup_uniform_float_copy(grp, "slicePosition", mds->slice_depth);
DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis);
DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT);
@@ -178,8 +177,8 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
double noise_ofs;
BLI_halton_1d(3, 0.0, effect_info->jitter_index, &noise_ofs);
float dim[3], step_length, max_slice;
- float slice_ct[3] = {sds->res[0], sds->res[1], sds->res[2]};
- mul_v3_fl(slice_ct, max_ff(0.001f, sds->slice_per_voxel));
+ float slice_ct[3] = {mds->res[0], mds->res[1], mds->res[2]};
+ mul_v3_fl(slice_ct, max_ff(0.001f, mds->slice_per_voxel));
max_slice = max_fff(slice_ct[0], slice_ct[1], slice_ct[2]);
BKE_object_dimensions_get(ob, dim);
invert_v3(slice_ct);
@@ -194,25 +193,25 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
}
- if (sds->use_coba) {
- DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex_field);
- DRW_shgroup_uniform_texture(grp, "transferTexture", sds->tex_coba);
+ if (mds->use_coba) {
+ DRW_shgroup_uniform_texture(grp, "densityTexture", mds->tex_field);
+ DRW_shgroup_uniform_texture(grp, "transferTexture", mds->tex_coba);
}
else {
static float white[3] = {1.0f, 1.0f, 1.0f};
- bool use_constant_color = ((sds->active_fields & SM_ACTIVE_COLORS) == 0 &&
- (sds->active_fields & SM_ACTIVE_COLOR_SET) != 0);
- DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex);
- DRW_shgroup_uniform_texture(grp, "shadowTexture", sds->tex_shadow);
+ bool use_constant_color = ((mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
+ (mds->active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET) != 0);
+ DRW_shgroup_uniform_texture(grp, "densityTexture", mds->tex);
+ DRW_shgroup_uniform_texture(grp, "shadowTexture", mds->tex_shadow);
DRW_shgroup_uniform_texture(
- grp, "flameTexture", (sds->tex_flame) ? sds->tex_flame : e_data.dummy_tex);
+ grp, "flameTexture", (mds->tex_flame) ? mds->tex_flame : e_data.dummy_tex);
DRW_shgroup_uniform_texture(
- grp, "flameColorTexture", (sds->tex_flame) ? sds->tex_flame_coba : e_data.dummy_coba_tex);
+ grp, "flameColorTexture", (mds->tex_flame) ? mds->tex_flame_coba : e_data.dummy_coba_tex);
DRW_shgroup_uniform_vec3(
- grp, "activeColor", (use_constant_color) ? sds->active_color : white, 1);
+ grp, "activeColor", (use_constant_color) ? mds->active_color : white, 1);
}
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness);
+ DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * mds->display_thickness);
if (use_slice) {
DRW_shgroup_call(grp, DRW_cache_quad_get(), ob);
@@ -221,7 +220,7 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
DRW_shgroup_call(grp, DRW_cache_cube_get(), ob);
}
- BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd));
+ BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(mmd));
}
void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd)
@@ -233,8 +232,8 @@ void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd)
* modifier is not used for display. We should share them for
* all viewport in a redraw at least. */
for (LinkData *link = wpd->smoke_domains.first; link; link = link->next) {
- SmokeModifierData *smd = (SmokeModifierData *)link->data;
- GPU_free_smoke(smd);
+ FluidModifierData *mmd = (FluidModifierData *)link->data;
+ GPU_free_smoke(mmd);
}
BLI_freelistN(&wpd->smoke_domains);
}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index a486eb6ba77..97afb5e6aa4 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -23,10 +23,8 @@
#ifndef __DRAW_COMMON_H__
#define __DRAW_COMMON_H__
-struct DRWCallBuffer;
struct DRWPass;
struct DRWShadingGroup;
-struct GPUBatch;
struct GPUMaterial;
struct ModifierData;
struct Object;
diff --git a/source/blender/draw/intern/draw_manager_text.c b/source/blender/draw/intern/draw_manager_text.c
index 9462a0d8072..38e8544de07 100644
--- a/source/blender/draw/intern/draw_manager_text.c
+++ b/source/blender/draw/intern/draw_manager_text.c
@@ -526,4 +526,4 @@ void DRW_text_edit_mesh_measure_stats(ARegion *ar,
}
}
}
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/intern/draw_manager_text.h b/source/blender/draw/intern/draw_manager_text.h
index a8eb45ee8f5..393645e614a 100644
--- a/source/blender/draw/intern/draw_manager_text.h
+++ b/source/blender/draw/intern/draw_manager_text.h
@@ -23,11 +23,11 @@
#ifndef __DRAW_MANAGER_TEXT_H__
#define __DRAW_MANAGER_TEXT_H__
-struct DRWTextStore;
struct ARegion;
-struct View3D;
+struct DRWTextStore;
struct Object;
struct UnitSettings;
+struct View3D;
struct DRWTextStore *DRW_text_cache_create(void);
void DRW_text_cache_destroy(struct DRWTextStore *dt);
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index fd8fe103a2d..4cc0c865093 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -385,9 +385,8 @@ set(ICON_NAMES
mod_mask
mod_cloth
mod_explode
- mod_fluidsim
mod_multires
- mod_smoke
+ mod_fluid
mod_solidify
mod_screw
mod_vertex_weight
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 5afb645d9e7..8ffae0f2b66 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -25,7 +25,6 @@
#define __ED_MBALL_H__
struct Base;
-struct MetaBall;
struct Object;
struct UndoType;
struct bContext;
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 5f7730a94e3..29bac9df93a 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -27,8 +27,6 @@
/* ******************* Registration Function ********************** */
struct Object;
-struct SnapObjectContext;
-struct SnapObjectParams;
struct bContext;
struct wmKeyConfig;
struct wmOperatorType;
@@ -107,7 +105,6 @@ bool calculateTransformCenter(struct bContext *C,
struct Object;
struct Scene;
-struct TransInfo;
struct wmGizmoGroup;
struct wmGizmoGroupType;
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 2bf50d3b4b8..44c734e264a 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -560,7 +560,7 @@ DEF_ICON_MODIFIER(MOD_CLOTH)
DEF_ICON_MODIFIER(MOD_EXPLODE)
DEF_ICON_MODIFIER(MOD_FLUIDSIM)
DEF_ICON_MODIFIER(MOD_MULTIRES)
-DEF_ICON_MODIFIER(MOD_SMOKE)
+DEF_ICON_MODIFIER(MOD_FLUID)
DEF_ICON_MODIFIER(MOD_SOLIDIFY)
DEF_ICON_MODIFIER(MOD_SCREW)
DEF_ICON_MODIFIER(MOD_VERTEX_WEIGHT)
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 17247736d3b..2c93f35e02a 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1819,11 +1819,13 @@ static int modifier_can_delete(ModifierData *md)
{
/* fluid particle modifier can't be deleted here */
if (md->type == eModifierType_ParticleSystem) {
- if (((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID) {
+ short particle_type = ((ParticleSystemModifierData *)md)->psys->part->type;
+ if (particle_type == PART_FLUID || particle_type == PART_FLUID_FLIP ||
+ particle_type == PART_FLUID_FOAM || particle_type == PART_FLUID_SPRAY ||
+ particle_type == PART_FLUID_BUBBLE || particle_type == PART_FLUID_BUBBLE) {
return 0;
}
}
-
return 1;
}
@@ -1836,7 +1838,7 @@ static int modifier_is_simulation(ModifierData *md)
eModifierType_Cloth,
eModifierType_Collision,
eModifierType_Fluidsim,
- eModifierType_Smoke,
+ eModifierType_Fluid,
eModifierType_Softbody,
eModifierType_Surface,
eModifierType_DynamicPaint)) {
@@ -2069,7 +2071,7 @@ static uiLayout *draw_modifier(uiLayout *layout,
eModifierType_Softbody,
eModifierType_ParticleSystem,
eModifierType_Cloth,
- eModifierType_Smoke)) {
+ eModifierType_Fluid)) {
uiItemO(row,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"),
ICON_NONE,
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index 021c17a94c2..0998280c381 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -27,6 +27,7 @@ set(INC
../../windowmanager
../../../../intern/glew-mx
../../../../intern/guardedalloc
+ ../../../../intern/mantaflow/extern
)
set(INC_SYS
@@ -56,19 +57,10 @@ set(LIB
)
if(WITH_MOD_FLUID)
- list(APPEND INC
- ../../../../intern/elbeem/extern
- )
- list(APPEND LIB
- bf_intern_elbeem
- )
- add_definitions(-DWITH_MOD_FLUID)
-endif()
-
-if(WITH_MOD_SMOKE)
list(APPEND LIB
- bf_intern_smoke
+ bf_intern_mantaflow
)
+ add_definitions(-DWITH_FLUID)
endif()
if(WITH_INTERNATIONAL)
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index cfb3a400f47..4df74434c6a 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -1065,7 +1065,7 @@ static void remove_particle_systems_from_object(Object *ob_to)
if (ELEM(md->type,
eModifierType_ParticleSystem,
eModifierType_DynamicPaint,
- eModifierType_Smoke)) {
+ eModifierType_Fluid)) {
BLI_remlink(&ob_to->modifiers, md);
modifier_free(md);
}
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 44858e36fab..5414c2a44a2 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -18,7 +18,7 @@
*/
/** \file
- * \ingroup edphys
+ * \ingroup edphys
*/
#include <math.h>
@@ -31,1219 +31,808 @@
/* types */
#include "DNA_action_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_fluidsim_types.h"
+#include "BLI_blenlib.h"
+#include "BLI_path_util.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_fluidsim.h"
+#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_fluid.h"
+#include "BKE_global.h"
#include "DEG_depsgraph.h"
#include "ED_screen.h"
-#include "ED_object.h"
+#include "PIL_time.h"
#include "WM_types.h"
#include "WM_api.h"
#include "physics_intern.h" // own include
+#include "manta_fluid_API.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_fluid_types.h"
+#include "DNA_mesh_types.h"
+
+#define FLUID_JOB_BAKE_ALL "FLUID_OT_bake_all"
+#define FLUID_JOB_BAKE_DATA "FLUID_OT_bake_data"
+#define FLUID_JOB_BAKE_NOISE "FLUID_OT_bake_noise"
+#define FLUID_JOB_BAKE_MESH "FLUID_OT_bake_mesh"
+#define FLUID_JOB_BAKE_PARTICLES "FLUID_OT_bake_particles"
+#define FLUID_JOB_BAKE_GUIDES "FLUID_OT_bake_guides"
+#define FLUID_JOB_FREE_ALL "FLUID_OT_free_all"
+#define FLUID_JOB_FREE_DATA "FLUID_OT_free_data"
+#define FLUID_JOB_FREE_NOISE "FLUID_OT_free_noise"
+#define FLUID_JOB_FREE_MESH "FLUID_OT_free_mesh"
+#define FLUID_JOB_FREE_PARTICLES "FLUID_OT_free_particles"
+#define FLUID_JOB_FREE_GUIDES "FLUID_OT_free_guides"
+#define FLUID_JOB_BAKE_PAUSE "FLUID_OT_pause_bake"
+
+typedef struct FluidJob {
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+ float *progress;
+ const char *type;
+ const char *name;
-/* enable/disable overall compilation */
-#ifdef WITH_MOD_FLUID
-
-# include "LBM_fluidsim.h"
-
-# include "BLI_blenlib.h"
-# include "BLI_path_util.h"
-# include "BLI_math.h"
+ struct Main *bmain;
+ Scene *scene;
+ Depsgraph *depsgraph;
+ Object *ob;
-# include "BKE_global.h"
-# include "BKE_main.h"
+ FluidModifierData *mmd;
-# include "WM_api.h"
+ int success;
+ double start;
-# include "DNA_scene_types.h"
-# include "DNA_mesh_types.h"
+ int *pause_frame;
+} FluidJob;
-static float get_fluid_viscosity(FluidsimSettings *settings)
+static inline bool fluid_is_bake_all(FluidJob *job)
{
- return (1.0f / powf(10.0f, settings->viscosityExponent)) * settings->viscosityValue;
+ return (STREQ(job->type, FLUID_JOB_BAKE_ALL));
}
-
-static float get_fluid_rate(FluidsimSettings *settings)
+static inline bool fluid_is_bake_data(FluidJob *job)
{
- float rate = 1.0f; /* default rate if not animated... */
-
- rate = settings->animRate;
-
- if (rate < 0.0f) {
- rate = 0.0f;
- }
-
- return rate;
+ return (STREQ(job->type, FLUID_JOB_BAKE_DATA));
}
-
-static void get_fluid_gravity(float *gravity, Scene *scene, FluidsimSettings *fss)
+static inline bool fluid_is_bake_noise(FluidJob *job)
{
- if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
- copy_v3_v3(gravity, scene->physics_settings.gravity);
- }
- else {
- copy_v3_v3(gravity, fss->grav);
- }
+ return (STREQ(job->type, FLUID_JOB_BAKE_NOISE));
}
-
-static float get_fluid_size_m(Scene *scene, Object *domainob, FluidsimSettings *fss)
+static inline bool fluid_is_bake_mesh(FluidJob *job)
{
- if (!scene->unit.system) {
- return fss->realsize;
- }
- else {
- float dim[3];
- float longest_axis;
-
- BKE_object_dimensions_get(domainob, dim);
- longest_axis = max_fff(dim[0], dim[1], dim[2]);
-
- return longest_axis * scene->unit.scale_length;
- }
+ return (STREQ(job->type, FLUID_JOB_BAKE_MESH));
}
-
-static bool fluid_is_animated_mesh(FluidsimSettings *fss)
+static inline bool fluid_is_bake_particle(FluidJob *job)
{
- return ((fss->type == OB_FLUIDSIM_CONTROL) || fss->domainNovecgen);
+ return (STREQ(job->type, FLUID_JOB_BAKE_PARTICLES));
}
-
-/* ********************** fluid sim settings struct functions ********************** */
-
-# if 0
-/* helper function */
-void fluidsimGetGeometryObjFilename(Object *ob, char *dst) //, char *srcname)
+static inline bool fluid_is_bake_guiding(FluidJob *job)
{
- //BLI_snprintf(dst, FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
- BLI_snprintf(dst, FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
+ return (STREQ(job->type, FLUID_JOB_BAKE_GUIDES));
}
-# endif
-
-/* ********************** fluid sim channel helper functions ********************** */
-
-typedef struct FluidAnimChannels {
- int length;
-
- double aniFrameTime;
-
- float *timeAtFrame;
- float *DomainTime;
- float *DomainGravity;
- float *DomainViscosity;
-} FluidAnimChannels;
-
-typedef struct FluidObject {
- struct FluidObject *next, *prev;
-
- struct Object *object;
-
- float *Translation;
- float *Rotation;
- float *Scale;
- float *Active;
-
- float *InitialVelocity;
-
- float *AttractforceStrength;
- float *AttractforceRadius;
- float *VelocityforceStrength;
- float *VelocityforceRadius;
-
- float *VertexCache;
- int numVerts, numTris;
-} FluidObject;
-
-// no. of entries for the two channel sizes
-# define CHANNEL_FLOAT 1
-# define CHANNEL_VEC 3
-
-// simplify channels before printing
-// for API this is done anyway upon init
-# if 0
-static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries)
+static inline bool fluid_is_free_all(FluidJob *job)
{
- int i, j;
- int channelSize = paramsize;
-
- if (entries == 3) {
- elbeemSimplifyChannelVec3(channel, &channelSize);
- }
- else if (entries == 1) {
- elbeemSimplifyChannelFloat(channel, &channelSize);
- }
- else {
- /* invalid, cant happen? */
- }
-
- fprintf(file, " CHANNEL %s =\n", str);
- for (i = 0; i < channelSize; i++) {
- fprintf(file, " ");
- for (j = 0; j <= entries; j++) { // also print time value
- fprintf(file, " %f ", channel[i * (entries + 1) + j]);
- if (j == entries - 1) {
- fprintf(file, " ");
- }
- }
- fprintf(file, "\n");
- }
-
- fprintf(file, " ;\n");
+ return (STREQ(job->type, FLUID_JOB_FREE_ALL));
}
-# endif
-
-/* Note: fluid anim channel data layout
- * ------------------------------------
- * CHANNEL_FLOAT:
- * frame 1 |frame 2
- * [dataF][time][dataF][time]
- *
- * CHANNEL_VEC:
- * frame 1 |frame 2
- * [dataX][dataY][dataZ][time][dataX][dataY][dataZ][time]
- */
-
-static void init_time(FluidsimSettings *domainSettings, FluidAnimChannels *channels)
+static inline bool fluid_is_free_data(FluidJob *job)
{
- int i;
-
- channels->timeAtFrame = MEM_callocN((channels->length + 1) * sizeof(float),
- "timeAtFrame channel");
-
- channels->timeAtFrame[0] = channels->timeAtFrame[1] =
- domainSettings->animStart; // start at index 1
-
- for (i = 2; i <= channels->length; i++) {
- channels->timeAtFrame[i] = channels->timeAtFrame[i - 1] + (float)channels->aniFrameTime;
- }
+ return (STREQ(job->type, FLUID_JOB_FREE_DATA));
}
-
-/* if this is slow, can replace with faster, less readable code */
-static void set_channel(float *channel, float time, float *value, int i, int size)
+static inline bool fluid_is_free_noise(FluidJob *job)
{
- if (size == CHANNEL_FLOAT) {
- channel[(i * 2) + 0] = value[0];
- channel[(i * 2) + 1] = time;
- }
- else if (size == CHANNEL_VEC) {
- channel[(i * 4) + 0] = value[0];
- channel[(i * 4) + 1] = value[1];
- channel[(i * 4) + 2] = value[2];
- channel[(i * 4) + 3] = time;
- }
+ return (STREQ(job->type, FLUID_JOB_FREE_NOISE));
}
-
-static void set_vertex_channel(Depsgraph *depsgraph,
- float *channel,
- float time,
- struct Scene *scene,
- struct FluidObject *fobj,
- int i)
+static inline bool fluid_is_free_mesh(FluidJob *job)
{
- Object *ob = fobj->object;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
- ob, eModifierType_Fluidsim);
- float *verts;
- int *tris = NULL, numVerts = 0, numTris = 0;
- int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
- int framesize = (3 * fobj->numVerts) + 1;
- int j;
-
- if (channel == NULL) {
- return;
- }
+ return (STREQ(job->type, FLUID_JOB_FREE_MESH));
+}
+static inline bool fluid_is_free_particles(FluidJob *job)
+{
+ return (STREQ(job->type, FLUID_JOB_FREE_PARTICLES));
+}
+static inline bool fluid_is_free_guiding(FluidJob *job)
+{
+ return (STREQ(job->type, FLUID_JOB_FREE_GUIDES));
+}
- initElbeemMesh(depsgraph, scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
+static bool fluid_initjob(
+ bContext *C, FluidJob *job, wmOperator *op, char *error_msg, int error_size)
+{
+ FluidModifierData *mmd = NULL;
+ FluidDomainSettings *mds;
+ Object *ob = CTX_data_active_object(C);
- /* don't allow mesh to change number of verts in anim sequence */
- if (numVerts != fobj->numVerts) {
- MEM_freeN(channel);
- channel = NULL;
- return;
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ if (!mmd) {
+ BLI_strncpy(error_msg, N_("Bake failed: no Fluid modifier found"), error_size);
+ return false;
}
-
- /* fill frame of channel with vertex locations */
- for (j = 0; j < (3 * numVerts); j++) {
- channel[i * framesize + j] = verts[j];
+ mds = mmd->domain;
+ if (!mds) {
+ BLI_strncpy(error_msg, N_("Bake failed: invalid domain"), error_size);
+ return false;
}
- channel[i * framesize + framesize - 1] = time;
- MEM_freeN(verts);
- MEM_freeN(tris);
-}
+ job->bmain = CTX_data_main(C);
+ job->scene = CTX_data_scene(C);
+ job->depsgraph = CTX_data_depsgraph_pointer(C);
+ job->ob = CTX_data_active_object(C);
+ job->mmd = mmd;
+ job->type = op->type->idname;
+ job->name = op->type->name;
-static void free_domain_channels(FluidAnimChannels *channels)
-{
- if (!channels->timeAtFrame) {
- return;
- }
- MEM_freeN(channels->timeAtFrame);
- channels->timeAtFrame = NULL;
- MEM_freeN(channels->DomainGravity);
- channels->DomainGravity = NULL;
- MEM_freeN(channels->DomainViscosity);
- channels->DomainViscosity = NULL;
- MEM_freeN(channels->DomainTime);
- channels->DomainTime = NULL;
+ return true;
}
-static void free_all_fluidobject_channels(ListBase *fobjects)
+static bool fluid_initpaths(FluidJob *job, ReportList *reports)
{
- FluidObject *fobj;
-
- for (fobj = fobjects->first; fobj; fobj = fobj->next) {
- if (fobj->Translation) {
- MEM_freeN(fobj->Translation);
- fobj->Translation = NULL;
- MEM_freeN(fobj->Rotation);
- fobj->Rotation = NULL;
- MEM_freeN(fobj->Scale);
- fobj->Scale = NULL;
- MEM_freeN(fobj->Active);
- fobj->Active = NULL;
- MEM_freeN(fobj->InitialVelocity);
- fobj->InitialVelocity = NULL;
- }
-
- if (fobj->AttractforceStrength) {
- MEM_freeN(fobj->AttractforceStrength);
- fobj->AttractforceStrength = NULL;
- MEM_freeN(fobj->AttractforceRadius);
- fobj->AttractforceRadius = NULL;
- MEM_freeN(fobj->VelocityforceStrength);
- fobj->VelocityforceStrength = NULL;
- MEM_freeN(fobj->VelocityforceRadius);
- fobj->VelocityforceRadius = NULL;
- }
+ FluidDomainSettings *mds = job->mmd->domain;
+ char temp_dir[FILE_MAX];
+ temp_dir[0] = '\0';
- if (fobj->VertexCache) {
- MEM_freeN(fobj->VertexCache);
- fobj->VertexCache = NULL;
- }
- }
-}
+ const char *relbase = modifier_path_relbase(job->bmain, job->ob);
-static void fluid_init_all_channels(bContext *C,
- Depsgraph *depsgraph,
- Object *UNUSED(fsDomain),
- FluidsimSettings *domainSettings,
- FluidAnimChannels *channels,
- ListBase *fobjects)
-{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base;
- int i;
- int length = channels->length;
- float eval_time;
-
- /* init time values (assuming that time moves at a constant speed; may be overridden later) */
- init_time(domainSettings, channels);
-
- /* allocate domain animation channels */
- 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->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
- "channel DomainTime");
-
- /* allocate fluid objects */
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
- Object *ob = base->object;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
- ob, eModifierType_Fluidsim);
-
- if (fluidmd) {
- FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object");
- fobj->object = ob;
-
- if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) {
- BLI_addtail(fobjects, fobj);
- continue;
- }
-
- fobj->Translation = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float),
- "fluidobject Translation");
- fobj->Rotation = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float),
- "fluidobject Rotation");
- fobj->Scale = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float), "fluidobject Scale");
- fobj->Active = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
- "fluidobject Active");
- fobj->InitialVelocity = MEM_callocN(length * (CHANNEL_VEC + 1) * sizeof(float),
- "fluidobject InitialVelocity");
-
- if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
- fobj->AttractforceStrength = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
- "fluidobject AttractforceStrength");
- fobj->AttractforceRadius = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
- "fluidobject AttractforceRadius");
- fobj->VelocityforceStrength = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
- "fluidobject VelocityforceStrength");
- fobj->VelocityforceRadius = MEM_callocN(length * (CHANNEL_FLOAT + 1) * sizeof(float),
- "fluidobject VelocityforceRadius");
- }
-
- if (fluid_is_animated_mesh(fluidmd->fss)) {
- float *verts = NULL;
- int *tris = NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd);
-
- initElbeemMesh(depsgraph,
- scene,
- ob,
- &fobj->numVerts,
- &verts,
- &fobj->numTris,
- &tris,
- 0,
- modifierIndex);
- fobj->VertexCache = MEM_callocN(length * ((fobj->numVerts * CHANNEL_VEC) + 1) *
- sizeof(float),
- "fluidobject VertexCache");
-
- MEM_freeN(verts);
- MEM_freeN(tris);
- }
-
- BLI_addtail(fobjects, fobj);
- }
+ /* We do not accept empty paths, they can end in random places silently, see T51176. */
+ if (mds->cache_directory[0] == '\0') {
+ modifier_path_init(
+ mds->cache_directory, sizeof(mds->cache_directory), FLUID_DOMAIN_DIR_DEFAULT);
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Fluid: Empty cache path, reset to default '%s'",
+ mds->cache_directory);
}
- /* now we loop over the frames and fill the allocated channels with data */
- for (i = 0; i < channels->length; i++) {
- FluidObject *fobj;
- float viscosity, gravity[3];
- float timeAtFrame, time;
+ BLI_strncpy(temp_dir, mds->cache_directory, FILE_MAXDIR);
+ BLI_path_abs(temp_dir, relbase);
- eval_time = domainSettings->bakeStart + i;
+ /* Ensure whole path exists */
+ const bool dir_exists = BLI_dir_create_recursive(temp_dir);
- /* Modifying the global scene isn't nice, but we can do it in
- * this part of the process before a threaded job is created */
- scene->r.cfra = (int)eval_time;
- ED_update_for_newframe(CTX_data_main(C), depsgraph);
+ /* We change path to some presumably valid default value, but do not allow bake process to
+ * continue, this gives user chance to set manually another path. */
+ if (!dir_exists) {
+ modifier_path_init(
+ mds->cache_directory, sizeof(mds->cache_directory), FLUID_DOMAIN_DIR_DEFAULT);
- /* now scene data should be current according to animation system, so we fill the channels */
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Fluid: Could not create cache directory '%s', reset to default '%s'",
+ temp_dir,
+ mds->cache_directory);
- /* 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) * (float)channels->aniFrameTime;
- timeAtFrame = channels->timeAtFrame[i] + time;
+ BLI_strncpy(temp_dir, mds->cache_directory, FILE_MAXDIR);
+ BLI_path_abs(temp_dir, relbase);
- channels->timeAtFrame[i + 1] = timeAtFrame;
- set_channel(channels->DomainTime, i, &time, i, CHANNEL_FLOAT);
- }
- else {
- timeAtFrame = channels->timeAtFrame[i + 1];
+ /* Ensure whole path exists and is writable. */
+ if (!BLI_dir_create_recursive(temp_dir)) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Fluid: Could not use default cache directory '%s', "
+ "please define a valid cache path manually",
+ temp_dir);
}
+ /* Copy final dir back into domain settings */
+ BLI_strncpy(mds->cache_directory, temp_dir, FILE_MAXDIR);
- /* Domain properties - gravity/viscosity */
- get_fluid_gravity(gravity, scene, domainSettings);
- set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC);
- viscosity = get_fluid_viscosity(domainSettings);
- set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT);
-
- /* object movement */
- for (fobj = fobjects->first; fobj; fobj = fobj->next) {
- Object *ob = fobj->object;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
- ob, eModifierType_Fluidsim);
- float active = (float)((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) ? 1 : 0);
- float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f};
-
- if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) {
- continue;
- }
-
- /* init euler rotation values and convert to elbeem format */
- /* get the rotation from ob->obmat rather than ob->rot to account for parent animations */
- if (i) {
- copy_v3_v3(old_rot, fobj->Rotation + 4 * (i - 1));
- mul_v3_fl(old_rot, (float)-M_PI / 180.f);
- }
-
- mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat);
- mul_v3_fl(rot_d, -180.0f / (float)M_PI);
-
- set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC);
- set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC);
- set_channel(fobj->Scale, timeAtFrame, ob->scale, i, CHANNEL_VEC);
- set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT);
- set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC);
-
- // printf("Active: %f, Frame: %f\n", active, timeAtFrame);
-
- if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
- set_channel(fobj->AttractforceStrength,
- timeAtFrame,
- &fluidmd->fss->attractforceStrength,
- i,
- CHANNEL_FLOAT);
- set_channel(fobj->AttractforceRadius,
- timeAtFrame,
- &fluidmd->fss->attractforceRadius,
- i,
- CHANNEL_FLOAT);
- set_channel(fobj->VelocityforceStrength,
- timeAtFrame,
- &fluidmd->fss->velocityforceStrength,
- i,
- CHANNEL_FLOAT);
- set_channel(fobj->VelocityforceRadius,
- timeAtFrame,
- &fluidmd->fss->velocityforceRadius,
- i,
- CHANNEL_FLOAT);
- }
-
- if (fluid_is_animated_mesh(fluidmd->fss)) {
- set_vertex_channel(depsgraph, fobj->VertexCache, timeAtFrame, scene, fobj, i);
- }
- }
+ return false;
}
+
+ /* Copy final dir back into domain settings */
+ BLI_strncpy(mds->cache_directory, temp_dir, FILE_MAXDIR);
+ return true;
}
-static void export_fluid_objects(Depsgraph *depsgraph,
- ListBase *fobjects,
- Scene *scene,
- int length)
+static void fluid_bake_free(void *customdata)
{
- FluidObject *fobj;
-
- for (fobj = fobjects->first; fobj; fobj = fobj->next) {
- Object *ob = fobj->object;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
- ob, eModifierType_Fluidsim);
- int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
+ FluidJob *job = customdata;
+ MEM_freeN(job);
+}
- float *verts = NULL;
- int *tris = NULL;
- int numVerts = 0, numTris = 0;
- bool deform = fluid_is_animated_mesh(fluidmd->fss);
+static void fluid_bake_sequence(FluidJob *job)
+{
+ FluidDomainSettings *mds = job->mmd->domain;
+ Scene *scene = job->scene;
+ int frame = 1, orig_frame;
+ int frames;
+ int *pause_frame = NULL;
+ bool is_first_frame;
- elbeemMesh fsmesh;
+ frames = mds->cache_frame_end - mds->cache_frame_start + 1;
- if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) {
- continue;
- }
+ if (frames <= 0) {
+ BLI_strncpy(mds->error, N_("No frames to bake"), sizeof(mds->error));
+ return;
+ }
- elbeemResetMesh(&fsmesh);
+ /* Show progress bar. */
+ if (job->do_update) {
+ *(job->do_update) = true;
+ }
- fsmesh.type = fluidmd->fss->type;
- fsmesh.name = ob->id.name;
+ /* Get current pause frame (pointer) - depending on bake type */
+ pause_frame = job->pause_frame;
- initElbeemMesh(depsgraph, scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
+ /* Set frame to start point (depending on current pause frame value) */
+ is_first_frame = ((*pause_frame) == 0);
+ frame = is_first_frame ? mds->cache_frame_start : (*pause_frame);
- fsmesh.numVertices = numVerts;
- fsmesh.numTriangles = numTris;
- fsmesh.vertices = verts;
- fsmesh.triangles = tris;
+ /* Save orig frame and update scene frame */
+ orig_frame = CFRA;
+ CFRA = frame;
- fsmesh.channelSizeTranslation = fsmesh.channelSizeRotation = fsmesh.channelSizeScale =
- fsmesh.channelSizeInitialVel = fsmesh.channelSizeActive = length;
+ /* Loop through selected frames */
+ for (; frame <= mds->cache_frame_end; frame++) {
+ const float progress = (frame - mds->cache_frame_start) / (float)frames;
- fsmesh.channelTranslation = fobj->Translation;
- fsmesh.channelRotation = fobj->Rotation;
- fsmesh.channelScale = fobj->Scale;
- fsmesh.channelActive = fobj->Active;
+ /* Keep track of pause frame - needed to init future loop */
+ (*pause_frame) = frame;
- if (ELEM(fsmesh.type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) {
- fsmesh.channelInitialVel = fobj->InitialVelocity;
- fsmesh.localInivelCoords = ((fluidmd->fss->typeFlags & OB_FSINFLOW_LOCALCOORD) ? 1 : 0);
+ /* If user requested stop, quit baking */
+ if (G.is_break) {
+ job->success = 0;
+ return;
}
- if (fluidmd->fss->typeFlags & OB_FSBND_NOSLIP) {
- fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
- }
- else if (fluidmd->fss->typeFlags & OB_FSBND_PARTSLIP) {
- fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ /* Update progress bar */
+ if (job->do_update) {
+ *(job->do_update) = true;
}
- else if (fluidmd->fss->typeFlags & OB_FSBND_FREESLIP) {
- fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
+ if (job->progress) {
+ *(job->progress) = progress;
}
- fsmesh.obstaclePartslip = fluidmd->fss->partSlipValue;
- fsmesh.volumeInitType = fluidmd->fss->volumeInitType;
- fsmesh.obstacleImpactFactor = fluidmd->fss->surfaceSmoothing; // misused value
-
- if (fsmesh.type == OB_FLUIDSIM_CONTROL) {
- fsmesh.cpsTimeStart = fluidmd->fss->cpsTimeStart;
- fsmesh.cpsTimeEnd = fluidmd->fss->cpsTimeEnd;
- fsmesh.cpsQuality = fluidmd->fss->cpsQuality;
- fsmesh.obstacleType = (fluidmd->fss->flag & OB_FLUIDSIM_REVERSE);
+ CFRA = frame;
- fsmesh.channelSizeAttractforceRadius = fsmesh.channelSizeVelocityforceStrength =
- fsmesh.channelSizeVelocityforceRadius = fsmesh.channelSizeAttractforceStrength = length;
-
- fsmesh.channelAttractforceStrength = fobj->AttractforceStrength;
- fsmesh.channelAttractforceRadius = fobj->AttractforceRadius;
- fsmesh.channelVelocityforceStrength = fobj->VelocityforceStrength;
- fsmesh.channelVelocityforceRadius = fobj->VelocityforceRadius;
- }
- else {
- fsmesh.channelAttractforceStrength = fsmesh.channelAttractforceRadius =
- fsmesh.channelVelocityforceStrength = fsmesh.channelVelocityforceRadius = NULL;
- }
-
- /* animated meshes */
- if (deform) {
- fsmesh.channelSizeVertices = length;
- fsmesh.channelVertices = fobj->VertexCache;
-
- /* remove channels */
- fsmesh.channelTranslation = fsmesh.channelRotation = fsmesh.channelScale = NULL;
-
- /* Override user settings, only noslip is supported here! */
- if (fsmesh.type != OB_FLUIDSIM_CONTROL) {
- fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
- }
- }
+ /* Update animation system */
+ ED_update_for_newframe(job->bmain, job->depsgraph);
+ }
- elbeemAddMesh(&fsmesh);
+ /* Restore frame position that we were on before bake */
+ CFRA = orig_frame;
+}
- if (verts) {
- MEM_freeN(verts);
+static void fluid_bake_endjob(void *customdata)
+{
+ FluidJob *job = customdata;
+ FluidDomainSettings *mds = job->mmd->domain;
+
+ if (fluid_is_bake_noise(job) || fluid_is_bake_all(job)) {
+ mds->cache_flag &= ~FLUID_DOMAIN_BAKING_NOISE;
+ mds->cache_flag |= FLUID_DOMAIN_BAKED_NOISE;
+ mds->cache_flag &= ~FLUID_DOMAIN_OUTDATED_NOISE;
+ }
+ if (fluid_is_bake_mesh(job) || fluid_is_bake_all(job)) {
+ mds->cache_flag &= ~FLUID_DOMAIN_BAKING_MESH;
+ mds->cache_flag |= FLUID_DOMAIN_BAKED_MESH;
+ mds->cache_flag &= ~FLUID_DOMAIN_OUTDATED_MESH;
+ }
+ if (fluid_is_bake_particle(job) || fluid_is_bake_all(job)) {
+ mds->cache_flag &= ~FLUID_DOMAIN_BAKING_PARTICLES;
+ mds->cache_flag |= FLUID_DOMAIN_BAKED_PARTICLES;
+ mds->cache_flag &= ~FLUID_DOMAIN_OUTDATED_PARTICLES;
+ }
+ if (fluid_is_bake_guiding(job) || fluid_is_bake_all(job)) {
+ mds->cache_flag &= ~FLUID_DOMAIN_BAKING_GUIDE;
+ mds->cache_flag |= FLUID_DOMAIN_BAKED_GUIDE;
+ mds->cache_flag &= ~FLUID_DOMAIN_OUTDATED_GUIDE;
+ }
+ if (fluid_is_bake_data(job) || fluid_is_bake_all(job)) {
+ mds->cache_flag &= ~FLUID_DOMAIN_BAKING_DATA;
+ mds->cache_flag |= FLUID_DOMAIN_BAKED_DATA;
+ mds->cache_flag &= ~FLUID_DOMAIN_OUTDATED_DATA;
+ }
+ DEG_id_tag_update(&job->ob->id, ID_RECALC_GEOMETRY);
+
+ G.is_rendering = false;
+ BKE_spacedata_draw_locks(false);
+ WM_set_locked_interface(G_MAIN->wm.first, false);
+
+ /* Bake was successful:
+ * Report for ended bake and how long it took */
+ if (job->success) {
+ /* Show bake info */
+ WM_reportf(
+ RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start);
+ }
+ else {
+ if (mds->error != NULL && mds->error[0] != '\0') {
+ WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error);
}
- if (tris) {
- MEM_freeN(tris);
+ else { /* User canceled the bake */
+ WM_reportf(RPT_WARNING, "Fluid: %s canceled!", job->name);
}
}
}
-static int fluid_validate_scene(ReportList *reports, ViewLayer *view_layer, Object *fsDomain)
+static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- Base *base;
- Object *newdomain = NULL;
- int channelObjCount = 0;
- int fluidInputCount = 0;
-
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
- Object *ob = base->object;
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(
- ob, eModifierType_Fluidsim);
-
- /* only find objects with fluid modifiers */
- if (!fluidmdtmp || ob->type != OB_MESH) {
- continue;
- }
-
- if (fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) {
- /* if no initial domain object given, find another potential domain */
- if (!fsDomain) {
- newdomain = ob;
- }
- /* if there's more than one domain, cancel */
- else if (fsDomain && ob != fsDomain) {
- BKE_report(reports, RPT_ERROR, "There should be only one domain object");
- return 0;
- }
- }
-
- /* count number of objects needed for animation channels */
- if (!ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) {
- channelObjCount++;
- }
-
- /* count number of fluid input objects */
- if (ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) {
- fluidInputCount++;
+ FluidJob *job = customdata;
+ FluidDomainSettings *mds = job->mmd->domain;
+
+ char temp_dir[FILE_MAX];
+
+ job->stop = stop;
+ job->do_update = do_update;
+ job->progress = progress;
+ job->start = PIL_check_seconds_timer();
+ job->success = 1;
+
+ G.is_break = false;
+ G.is_rendering = true;
+ BKE_spacedata_draw_locks(true);
+
+ if (fluid_is_bake_noise(job) || fluid_is_bake_all(job)) {
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL);
+ BLI_dir_create_recursive(temp_dir); /* Create 'noise' subdir if it does not exist already */
+ mds->cache_flag &= ~(FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_OUTDATED_NOISE);
+ mds->cache_flag |= FLUID_DOMAIN_BAKING_NOISE;
+ job->pause_frame = &mds->cache_frame_pause_noise;
+ }
+ if (fluid_is_bake_mesh(job) || fluid_is_bake_all(job)) {
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL);
+ BLI_dir_create_recursive(temp_dir); /* Create 'mesh' subdir if it does not exist already */
+ mds->cache_flag &= ~(FLUID_DOMAIN_BAKED_MESH | FLUID_DOMAIN_OUTDATED_MESH);
+ mds->cache_flag |= FLUID_DOMAIN_BAKING_MESH;
+ job->pause_frame = &mds->cache_frame_pause_mesh;
+ }
+ if (fluid_is_bake_particle(job) || fluid_is_bake_all(job)) {
+ BLI_path_join(
+ temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL);
+ BLI_dir_create_recursive(
+ temp_dir); /* Create 'particles' subdir if it does not exist already */
+ mds->cache_flag &= ~(FLUID_DOMAIN_BAKED_PARTICLES | FLUID_DOMAIN_OUTDATED_PARTICLES);
+ mds->cache_flag |= FLUID_DOMAIN_BAKING_PARTICLES;
+ job->pause_frame = &mds->cache_frame_pause_particles;
+ }
+ if (fluid_is_bake_guiding(job) || fluid_is_bake_all(job)) {
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL);
+ BLI_dir_create_recursive(temp_dir); /* Create 'guiding' subdir if it does not exist already */
+ mds->cache_flag &= ~(FLUID_DOMAIN_BAKED_GUIDE | FLUID_DOMAIN_OUTDATED_GUIDE);
+ mds->cache_flag |= FLUID_DOMAIN_BAKING_GUIDE;
+ job->pause_frame = &mds->cache_frame_pause_guide;
+ }
+ if (fluid_is_bake_data(job) || fluid_is_bake_all(job)) {
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL);
+ BLI_dir_create_recursive(temp_dir); /* Create 'config' subdir if it does not exist already */
+
+ BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL);
+ BLI_dir_create_recursive(temp_dir); /* Create 'data' subdir if it does not exist already */
+ mds->cache_flag &= ~(FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA);
+ mds->cache_flag |= FLUID_DOMAIN_BAKING_DATA;
+ job->pause_frame = &mds->cache_frame_pause_data;
+
+ if (mds->flags & FLUID_DOMAIN_EXPORT_MANTA_SCRIPT) {
+ BLI_path_join(
+ temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL);
+ BLI_dir_create_recursive(temp_dir); /* Create 'script' subdir if it does not exist already */
}
}
+ DEG_id_tag_update(&job->ob->id, ID_RECALC_GEOMETRY);
- if (newdomain) {
- fsDomain = newdomain;
- }
+ fluid_bake_sequence(job);
- if (!fsDomain) {
- BKE_report(reports, RPT_ERROR, "No domain object found");
- return 0;
+ if (do_update) {
+ *do_update = true;
}
-
- if (channelObjCount >= 255) {
- BKE_report(reports, RPT_ERROR, "Cannot bake with more than 256 objects");
- return 0;
+ if (stop) {
+ *stop = 0;
}
-
- if (fluidInputCount == 0) {
- BKE_report(reports, RPT_ERROR, "No fluid input objects in the scene");
- return 0;
- }
-
- return 1;
}
-# define FLUID_SUFFIX_CONFIG "fluidsim.cfg"
-# define FLUID_SUFFIX_CONFIG_TMP (FLUID_SUFFIX_CONFIG ".tmp")
-# define FLUID_SUFFIX_SURFACE "fluidsurface"
-
-static bool fluid_init_filepaths(Main *bmain,
- ReportList *reports,
- FluidsimSettings *domainSettings,
- Object *fsDomain,
- char *targetDir,
- char *targetFile)
+static void fluid_free_endjob(void *customdata)
{
- const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
+ FluidJob *job = customdata;
+ FluidDomainSettings *mds = job->mmd->domain;
- /* prepare names... */
- const char *relbase = modifier_path_relbase(bmain, fsDomain);
+ G.is_rendering = false;
+ BKE_spacedata_draw_locks(false);
+ WM_set_locked_interface(G_MAIN->wm.first, false);
- /* We do not accept empty paths, they can end in random places silently, see T51176. */
- if (domainSettings->surfdataPath[0] == '\0') {
- modifier_path_init(domainSettings->surfdataPath,
- sizeof(domainSettings->surfdataPath),
- OB_FLUIDSIM_SURF_DIR_DEFAULT);
- BKE_reportf(reports,
- RPT_WARNING,
- "Fluidsim: empty cache path, reset to default '%s'",
- domainSettings->surfdataPath);
+ /* Free was successful:
+ * Report for ended free job and how long it took */
+ if (job->success) {
+ /* Show free job info */
+ WM_reportf(
+ RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start);
}
-
- BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
- BLI_path_abs(targetDir, relbase);
-
- /* .tmp: don't overwrite/delete original file */
- BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
-
- /* Ensure whole path exists and is writeable. */
- const bool dir_exists = BLI_dir_create_recursive(targetDir);
- const bool is_writable = BLI_file_is_writable(targetFile);
-
- /* We change path to some presumably valid default value,
- * but do not allow bake process to continue,
- * this gives user chance to set manually another path. */
- if (!dir_exists || !is_writable) {
- modifier_path_init(domainSettings->surfdataPath,
- sizeof(domainSettings->surfdataPath),
- OB_FLUIDSIM_SURF_DIR_DEFAULT);
-
- if (!dir_exists) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Fluidsim: could not create cache directory '%s', reset to default '%s'",
- targetDir,
- domainSettings->surfdataPath);
+ else {
+ if (mds->error != NULL && mds->error[0] != '\0') {
+ WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error);
}
- else {
- BKE_reportf(reports,
- RPT_ERROR,
- "Fluidsim: cache directory '%s' is not writable, reset to default '%s'",
- targetDir,
- domainSettings->surfdataPath);
+ else { /* User canceled the free job */
+ WM_reportf(RPT_WARNING, "Fluid: %s canceled!", job->name);
}
-
- BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
- BLI_path_abs(targetDir, relbase);
-
- /* .tmp: don't overwrite/delete original file */
- BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
-
- /* Ensure whole path exists and is writeable. */
- if (!BLI_dir_create_recursive(targetDir) || !BLI_file_is_writable(targetFile)) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Fluidsim: could not use default cache directory '%s', "
- "please define a valid cache path manually",
- targetDir);
- }
- return false;
}
-
- return true;
}
-/* ******************************************************************************** */
-/* ********************** write fluidsim config to file ************************* */
-/* ******************************************************************************** */
+static void fluid_free_startjob(void *customdata, short *stop, short *do_update, float *progress)
+{
+ FluidJob *job = customdata;
+ FluidDomainSettings *mds = job->mmd->domain;
+ Scene *scene = job->scene;
-typedef struct FluidBakeJob {
- /* from wmJob */
- void *owner;
- short *stop, *do_update;
- float *progress;
- int current_frame;
- elbeemSimulationSettings *settings;
-} FluidBakeJob;
+ job->stop = stop;
+ job->do_update = do_update;
+ job->progress = progress;
+ job->start = PIL_check_seconds_timer();
+ job->success = 1;
-static void fluidbake_free(void *customdata)
-{
- FluidBakeJob *fb = (FluidBakeJob *)customdata;
- MEM_freeN(fb);
-}
+ G.is_break = false;
+ G.is_rendering = true;
+ BKE_spacedata_draw_locks(true);
-/* called by fluidbake, only to check job 'stop' value */
-static int fluidbake_breakjob(void *customdata)
-{
- FluidBakeJob *fb = (FluidBakeJob *)customdata;
+ int cache_map = 0;
- if (fb->stop && *(fb->stop)) {
- return 1;
+ if (fluid_is_free_data(job) || fluid_is_free_all(job)) {
+ cache_map |= (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES);
+ }
+ if (fluid_is_free_noise(job) || fluid_is_free_all(job)) {
+ cache_map |= FLUID_DOMAIN_OUTDATED_NOISE;
+ }
+ if (fluid_is_free_mesh(job) || fluid_is_free_all(job)) {
+ cache_map |= FLUID_DOMAIN_OUTDATED_MESH;
+ }
+ if (fluid_is_free_particles(job) || fluid_is_free_all(job)) {
+ cache_map |= FLUID_DOMAIN_OUTDATED_PARTICLES;
+ }
+ if (fluid_is_free_guiding(job) || fluid_is_free_all(job)) {
+ cache_map |= FLUID_DOMAIN_OUTDATED_GUIDE;
}
+#ifdef WITH_FLUID
+ BKE_fluid_cache_free(mds, job->ob, cache_map);
+#endif
- /* this is not nice yet, need to make the jobs list template better
- * for identifying/acting upon various different jobs */
- /* but for now we'll reuse the render break... */
- return (G.is_break);
-}
+ *do_update = true;
+ *stop = 0;
-/* called by fluidbake, wmJob sends notifier */
-static void fluidbake_updatejob(void *customdata, float progress)
-{
- FluidBakeJob *fb = (FluidBakeJob *)customdata;
+ /* Reset scene frame to cache frame start */
+ CFRA = mds->cache_frame_start;
- *(fb->do_update) = true;
- *(fb->progress) = progress;
+ /* Update scene so that viewport shows freed up scene */
+ ED_update_for_newframe(job->bmain, job->depsgraph);
}
-static void fluidbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
-{
- FluidBakeJob *fb = (FluidBakeJob *)customdata;
+/***************************** Operators ******************************/
- fb->stop = stop;
- fb->do_update = do_update;
- fb->progress = progress;
+static int fluid_bake_exec(struct bContext *C, struct wmOperator *op)
+{
+ FluidJob *job = MEM_mallocN(sizeof(FluidJob), "FluidJob");
+ char error_msg[256] = "\0";
- G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
+ if (!fluid_initjob(C, job, op, error_msg, sizeof(error_msg))) {
+ if (error_msg[0]) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ }
+ fluid_bake_free(job);
+ return OPERATOR_CANCELLED;
+ }
+ if (!fluid_initpaths(job, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ fluid_bake_startjob(job, NULL, NULL, NULL);
+ fluid_bake_endjob(job);
+ fluid_bake_free(job);
- elbeemSimulate();
- *do_update = true;
- *stop = 0;
+ return OPERATOR_FINISHED;
}
-static void fluidbake_endjob(void *customdata)
+static int fluid_bake_invoke(struct bContext *C,
+ struct wmOperator *op,
+ const wmEvent *UNUSED(_event))
{
- FluidBakeJob *fb = (FluidBakeJob *)customdata;
+ Scene *scene = CTX_data_scene(C);
+ FluidJob *job = MEM_mallocN(sizeof(FluidJob), "FluidJob");
+ char error_msg[256] = "\0";
- if (fb->settings) {
- MEM_freeN(fb->settings);
- fb->settings = NULL;
+ if (!fluid_initjob(C, job, op, error_msg, sizeof(error_msg))) {
+ if (error_msg[0]) {
+ BKE_report(op->reports, RPT_ERROR, error_msg);
+ }
+ fluid_bake_free(job);
+ return OPERATOR_CANCELLED;
}
-}
-static int runSimulationCallback(void *data, int status, int frame)
-{
- FluidBakeJob *fb = (FluidBakeJob *)data;
- elbeemSimulationSettings *settings = fb->settings;
-
- if (status == FLUIDSIM_CBSTATUS_NEWFRAME) {
- fluidbake_updatejob(fb, frame / (float)settings->noOfFrames);
-# if 0
- printf("elbeem blender cb s%d, f%d, domainid:%d noOfFrames: %d\n",
- status,
- frame,
- settings->domainId,
- settings->noOfFrames); // DEBUG
-# endif
+ if (!fluid_initpaths(job, op->reports)) {
+ return OPERATOR_CANCELLED;
}
- if (fluidbake_breakjob(fb)) {
- return FLUIDSIM_CBRET_ABORT;
- }
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Fluid Bake",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_SIM_FLUID);
+
+ WM_jobs_customdata_set(wm_job, job, fluid_bake_free);
+ WM_jobs_timer(wm_job, 0.01, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
+ WM_jobs_callbacks(wm_job, fluid_bake_startjob, NULL, NULL, fluid_bake_endjob);
+
+ WM_set_locked_interface(CTX_wm_manager(C), true);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_event_add_modal_handler(C, op);
- return FLUIDSIM_CBRET_CONTINUE;
+ return OPERATOR_RUNNING_MODAL;
}
-static void fluidbake_free_data(FluidAnimChannels *channels,
- ListBase *fobjects,
- elbeemSimulationSettings *fsset,
- FluidBakeJob *fb)
+static int fluid_bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- free_domain_channels(channels);
- MEM_freeN(channels);
- channels = NULL;
-
- free_all_fluidobject_channels(fobjects);
- BLI_freelistN(fobjects);
- MEM_freeN(fobjects);
- fobjects = NULL;
-
- if (fsset) {
- MEM_freeN(fsset);
- fsset = NULL;
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_SIM_FLUID)) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
- if (fb) {
- MEM_freeN(fb);
- fb = NULL;
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
}
+ return OPERATOR_PASS_THROUGH;
}
-/* copied from rna_fluidsim.c: fluidsim_find_lastframe() */
-static void fluidsim_delete_until_lastframe(FluidsimSettings *fss, const char *relbase)
+static int fluid_free_exec(struct bContext *C, struct wmOperator *op)
{
- char targetDir[FILE_MAX], targetFile[FILE_MAX];
- char targetDirVel[FILE_MAX], targetFileVel[FILE_MAX];
- char previewDir[FILE_MAX], previewFile[FILE_MAX];
- int curFrame = 1, exists = 0;
-
- BLI_join_dirfile(
- targetDir, sizeof(targetDir), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
- BLI_join_dirfile(
- targetDirVel, sizeof(targetDirVel), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_VEL_FNAME);
- BLI_join_dirfile(
- previewDir, sizeof(previewDir), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME);
-
- BLI_path_abs(targetDir, relbase);
- BLI_path_abs(targetDirVel, relbase);
- BLI_path_abs(previewDir, relbase);
-
- do {
- BLI_strncpy(targetFile, targetDir, sizeof(targetFile));
- BLI_strncpy(targetFileVel, targetDirVel, sizeof(targetFileVel));
- BLI_strncpy(previewFile, previewDir, sizeof(previewFile));
-
- BLI_path_frame(targetFile, curFrame, 0);
- BLI_path_frame(targetFileVel, curFrame, 0);
- BLI_path_frame(previewFile, curFrame, 0);
-
- curFrame++;
-
- if ((exists = BLI_exists(targetFile))) {
- BLI_delete(targetFile, false, false);
- BLI_delete(targetFileVel, false, false);
- BLI_delete(previewFile, false, false);
- }
- } while (exists);
+ FluidModifierData *mmd = NULL;
+ FluidDomainSettings *mds;
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
- return;
-}
+ /*
+ * Get modifier data
+ */
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ if (!mmd) {
+ BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found");
+ return OPERATOR_CANCELLED;
+ }
+ mds = mmd->domain;
+ if (!mds) {
+ BKE_report(op->reports, RPT_ERROR, "Bake free failed: invalid domain");
+ return OPERATOR_CANCELLED;
+ }
-static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, short do_job)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- int i;
- FluidsimSettings *domainSettings;
-
- char debugStrBuffer[256];
-
- int gridlevels = 0;
- const char *relbase = modifier_path_relbase(bmain, fsDomain);
- const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
- const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
- const char *suffixSurface = FLUID_SUFFIX_SURFACE;
-
- char targetDir[FILE_MAX]; // store & modify output settings
- char targetFile[FILE_MAX]; // temp. store filename from targetDir for access
-
- float domainMat[4][4];
- float invDomMat[4][4];
-
- int noFrames;
- int origFrame = scene->r.cfra;
-
- FluidAnimChannels *channels = MEM_callocN(sizeof(FluidAnimChannels),
- "fluid domain animation channels");
- ListBase *fobjects = MEM_callocN(sizeof(ListBase), "fluid objects");
- FluidsimModifierData *fluidmd = NULL;
- Mesh *mesh = NULL;
-
- FluidBakeJob *fb;
- elbeemSimulationSettings *fsset = MEM_callocN(sizeof(elbeemSimulationSettings),
- "Fluid sim settings");
-
- fb = MEM_callocN(sizeof(FluidBakeJob), "fluid bake job");
-
- if (BLI_getenv(strEnvName)) {
- int dlevel = atoi(BLI_getenv(strEnvName));
- elbeemSetDebugLevel(dlevel);
- BLI_snprintf(debugStrBuffer,
- sizeof(debugStrBuffer),
- "fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",
- strEnvName);
- elbeemDebugOut(debugStrBuffer);
+ /* Cannot free data if other bakes currently working */
+ if (mmd->domain->cache_flag & (FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKING_NOISE |
+ FLUID_DOMAIN_BAKING_MESH | FLUID_DOMAIN_BAKING_PARTICLES)) {
+ BKE_report(op->reports, RPT_ERROR, "Bake free failed: pending bake jobs found");
+ return OPERATOR_CANCELLED;
}
- /* Make sure it corresponds to startFrame setting
- * (old: noFrames = scene->r.efra - scene->r.sfra +1). */
+ FluidJob *job = MEM_mallocN(sizeof(FluidJob), "FluidJob");
+ job->bmain = CTX_data_main(C);
+ job->scene = scene;
+ job->depsgraph = CTX_data_depsgraph_pointer(C);
+ job->ob = ob;
+ job->mmd = mmd;
+ job->type = op->type->idname;
+ job->name = op->type->name;
- noFrames = scene->r.efra - 0;
- if (noFrames <= 0) {
- BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)");
- fluidbake_free_data(channels, fobjects, fsset, fb);
- return 0;
+ if (!fluid_initpaths(job, op->reports)) {
+ return OPERATOR_CANCELLED;
}
- /* check scene for sane object/modifier settings */
- if (!fluid_validate_scene(reports, view_layer, fsDomain)) {
- fluidbake_free_data(channels, fobjects, fsset, fb);
- return 0;
- }
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Fluid Free",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_SIM_FLUID);
- /* these both have to be valid, otherwise we wouldn't be here */
- fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
- domainSettings = fluidmd->fss;
- mesh = fsDomain->data;
-
- domainSettings->bakeStart = 1;
- domainSettings->bakeEnd = scene->r.efra;
-
- // calculate bounding box
- fluid_get_bb(mesh->mvert,
- mesh->totvert,
- fsDomain->obmat,
- domainSettings->bbStart,
- domainSettings->bbSize);
-
- // reset last valid frame
- domainSettings->lastgoodframe = -1;
-
- /* delete old baked files */
- fluidsim_delete_until_lastframe(domainSettings, relbase);
-
- /* rough check of settings... */
- if (domainSettings->previewresxyz > domainSettings->resolutionxyz) {
- BLI_snprintf(debugStrBuffer,
- sizeof(debugStrBuffer),
- "fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n",
- domainSettings->previewresxyz,
- domainSettings->resolutionxyz);
- elbeemDebugOut(debugStrBuffer);
- domainSettings->previewresxyz = domainSettings->resolutionxyz;
- }
- // set adaptive coarsening according to resolutionxyz
- // this should do as an approximation, with in/outflow
- // doing this more accurate would be overkill
- // perhaps add manual setting?
- if (domainSettings->maxRefine < 0) {
- if (domainSettings->resolutionxyz > 128) {
- gridlevels = 2;
- }
- else if (domainSettings->resolutionxyz > 64) {
- gridlevels = 1;
- }
- else {
- gridlevels = 0;
- }
- }
- else {
- gridlevels = domainSettings->maxRefine;
- }
- BLI_snprintf(debugStrBuffer,
- sizeof(debugStrBuffer),
- "fluidsimBake::msg: Baking %s, refine: %d\n",
- fsDomain->id.name,
- gridlevels);
- elbeemDebugOut(debugStrBuffer);
-
- /* ******** prepare output file paths ******** */
- if (!fluid_init_filepaths(bmain, reports, domainSettings, fsDomain, targetDir, targetFile)) {
- fluidbake_free_data(channels, fobjects, fsset, fb);
- return false;
- }
+ WM_jobs_customdata_set(wm_job, job, fluid_bake_free);
+ WM_jobs_timer(wm_job, 0.01, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
+ WM_jobs_callbacks(wm_job, fluid_free_startjob, NULL, NULL, fluid_free_endjob);
- /* DG TODO: why using endframe and not "noFrames" here?
- * because "noFrames" is buggy too? (not using sfra) */
- channels->length = scene->r.efra;
- channels->aniFrameTime = (double)((double)domainSettings->animEnd -
- (double)domainSettings->animStart) /
- (double)noFrames;
-
- /* ******** initialize and allocate animation channels ******** */
- fluid_init_all_channels(C, depsgraph, fsDomain, domainSettings, channels, fobjects);
-
- /* reset to original current frame */
- scene->r.cfra = origFrame;
- ED_update_for_newframe(CTX_data_main(C), CTX_data_depsgraph_pointer(C));
-
- /* ******** init domain object's matrix ******** */
- copy_m4_m4(domainMat, fsDomain->obmat);
- if (!invert_m4_m4(invDomMat, domainMat)) {
- BLI_snprintf(
- debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - Invalid obj matrix?\n");
- elbeemDebugOut(debugStrBuffer);
- BKE_report(reports, RPT_ERROR, "Invalid object matrix");
-
- fluidbake_free_data(channels, fobjects, fsset, fb);
- return 0;
- }
+ WM_set_locked_interface(CTX_wm_manager(C), true);
- /* ******** start writing / exporting ******** */
- // use .tmp, don't overwrite/delete original file
- BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp);
-
- /* ******** export domain to elbeem ******** */
- elbeemResetSettings(fsset);
- fsset->version = 1;
- fsset->threads = (domainSettings->threads == 0) ? BKE_scene_num_threads(scene) :
- domainSettings->threads;
- // setup global settings
- copy_v3_v3(fsset->geoStart, domainSettings->bbStart);
- copy_v3_v3(fsset->geoSize, domainSettings->bbSize);
-
- // simulate with 50^3
- fsset->resolutionxyz = (int)domainSettings->resolutionxyz;
- fsset->previewresxyz = (int)domainSettings->previewresxyz;
-
- fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings);
- fsset->viscosity = get_fluid_viscosity(domainSettings);
- get_fluid_gravity(fsset->gravity, scene, domainSettings);
-
- // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
- fsset->animStart = domainSettings->animStart;
- fsset->aniFrameTime = channels->aniFrameTime;
- fsset->noOfFrames = noFrames; // is otherwise subtracted in parser
-
- BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixSurface);
-
- // defaults for compressibility and adaptive grids
- fsset->gstar = domainSettings->gstar;
- fsset->maxRefine = domainSettings->maxRefine; // check <-> gridlevels
- fsset->generateParticles = domainSettings->generateParticles;
- fsset->numTracerParticles = domainSettings->generateTracers;
- fsset->surfaceSmoothing = domainSettings->surfaceSmoothing;
- fsset->surfaceSubdivs = domainSettings->surfaceSubdivs;
- fsset->farFieldSize = domainSettings->farFieldSize;
- BLI_strncpy(fsset->outputPath, targetFile, sizeof(fsset->outputPath));
-
- // domain channels
- fsset->channelSizeFrameTime = fsset->channelSizeViscosity = fsset->channelSizeGravity =
- channels->length;
- fsset->channelFrameTime = channels->DomainTime;
- fsset->channelViscosity = channels->DomainViscosity;
- fsset->channelGravity = channels->DomainGravity;
-
- fsset->runsimCallback = &runSimulationCallback;
- fsset->runsimUserData = fb;
-
- if (domainSettings->typeFlags & OB_FSBND_NOSLIP) {
- fsset->domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
- }
- else if (domainSettings->typeFlags & OB_FSBND_PARTSLIP) {
- fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
- }
- else if (domainSettings->typeFlags & OB_FSBND_FREESLIP) {
- fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
- }
- fsset->domainobsPartslip = domainSettings->partSlipValue;
+ /* Free Fluid Geometry */
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+
+ return OPERATOR_FINISHED;
+}
- /* use domainobsType also for surface generation flag (bit: >=64) */
- if (domainSettings->typeFlags & OB_FSSG_NOOBS) {
- fsset->mFsSurfGenSetting = FLUIDSIM_FSSG_NOOBS;
+static int fluid_pause_exec(struct bContext *C, struct wmOperator *op)
+{
+ FluidModifierData *mmd = NULL;
+ FluidDomainSettings *mds;
+ Object *ob = CTX_data_active_object(C);
+
+ /*
+ * Get modifier data
+ */
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ if (!mmd) {
+ BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found");
+ return OPERATOR_CANCELLED;
}
- else {
- fsset->mFsSurfGenSetting = 0; // "normal" mode
+ mds = mmd->domain;
+ if (!mds) {
+ BKE_report(op->reports, RPT_ERROR, "Bake free failed: invalid domain");
+ return OPERATOR_CANCELLED;
}
- fsset->generateVertexVectors = (domainSettings->domainNovecgen == 0);
+ G.is_break = true;
- // init blender domain transform matrix
- {
- int j;
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- fsset->surfaceTrafo[i * 4 + j] = invDomMat[j][i];
- }
- }
- }
+ return OPERATOR_FINISHED;
+}
- /* ******** init solver with settings ******** */
- elbeemInit();
- elbeemAddDomain(fsset);
+void FLUID_OT_bake_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Bake All";
+ ot->description = "Bake Entire Fluid Simulation";
+ ot->idname = FLUID_JOB_BAKE_ALL;
- /* ******** export all fluid objects to elbeem ******** */
- export_fluid_objects(depsgraph, fobjects, scene, channels->length);
+ /* api callbacks */
+ ot->exec = fluid_bake_exec;
+ ot->invoke = fluid_bake_invoke;
+ ot->modal = fluid_bake_modal;
+ ot->poll = ED_operator_object_active_editable;
+}
- /* custom data for fluid bake job */
- fb->settings = fsset;
+void FLUID_OT_free_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Free All";
+ ot->description = "Free Entire Fluid Simulation";
+ ot->idname = FLUID_JOB_FREE_ALL;
- if (do_job) {
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
- CTX_wm_window(C),
- scene,
- "Fluid Simulation",
- WM_JOB_PROGRESS,
- WM_JOB_TYPE_OBJECT_SIM_FLUID);
+ /* api callbacks */
+ ot->exec = fluid_free_exec;
+ ot->poll = ED_operator_object_active_editable;
+}
- /* setup job */
- WM_jobs_customdata_set(wm_job, fb, fluidbake_free);
- WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
- WM_jobs_callbacks(wm_job, fluidbake_startjob, NULL, NULL, fluidbake_endjob);
+void FLUID_OT_bake_data(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Bake Data";
+ ot->description = "Bake Fluid Data";
+ ot->idname = FLUID_JOB_BAKE_DATA;
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- }
- else {
- short dummy_stop = 0, dummy_do_update = 0;
- float dummy_progress = 0.0f;
+ /* api callbacks */
+ ot->exec = fluid_bake_exec;
+ ot->invoke = fluid_bake_invoke;
+ ot->modal = fluid_bake_modal;
+ ot->poll = ED_operator_object_active_editable;
+}
- /* blocking, use with exec() */
- fluidbake_startjob((void *)fb, &dummy_stop, &dummy_do_update, &dummy_progress);
- fluidbake_endjob((void *)fb);
- fluidbake_free((void *)fb);
- }
+void FLUID_OT_free_data(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Free Data";
+ ot->description = "Free Fluid Data";
+ ot->idname = FLUID_JOB_FREE_DATA;
+
+ /* api callbacks */
+ ot->exec = fluid_free_exec;
+ ot->poll = ED_operator_object_active_editable;
+}
- /* ******** free stored animation data ******** */
- fluidbake_free_data(channels, fobjects, NULL, NULL);
+void FLUID_OT_bake_noise(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Bake Noise";
+ ot->description = "Bake Fluid Noise";
+ ot->idname = FLUID_JOB_BAKE_NOISE;
- // elbeemFree();
- return 1;
+ /* api callbacks */
+ ot->exec = fluid_bake_exec;
+ ot->invoke = fluid_bake_invoke;
+ ot->modal = fluid_bake_modal;
+ ot->poll = ED_operator_object_active_editable;
}
-static void UNUSED_FUNCTION(fluidsimFreeBake)(Object *UNUSED(ob))
+void FLUID_OT_free_noise(wmOperatorType *ot)
{
- /* not implemented yet */
+ /* identifiers */
+ ot->name = "Free Noise";
+ ot->description = "Free Fluid Noise";
+ ot->idname = FLUID_JOB_FREE_NOISE;
+
+ /* api callbacks */
+ ot->exec = fluid_free_exec;
+ ot->poll = ED_operator_object_active_editable;
}
-#else /* WITH_MOD_FLUID */
+void FLUID_OT_bake_mesh(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Bake Mesh";
+ ot->description = "Bake Fluid Mesh";
+ ot->idname = FLUID_JOB_BAKE_MESH;
+
+ /* api callbacks */
+ ot->exec = fluid_bake_exec;
+ ot->invoke = fluid_bake_invoke;
+ ot->modal = fluid_bake_modal;
+ ot->poll = ED_operator_object_active_editable;
+}
-/* only compile dummy functions */
-static int fluidsimBake(bContext *UNUSED(C),
- ReportList *UNUSED(reports),
- Object *UNUSED(ob),
- short UNUSED(do_job))
+void FLUID_OT_free_mesh(wmOperatorType *ot)
{
- return 0;
+ /* identifiers */
+ ot->name = "Free Mesh";
+ ot->description = "Free Fluid Mesh";
+ ot->idname = FLUID_JOB_FREE_MESH;
+
+ /* api callbacks */
+ ot->exec = fluid_free_exec;
+ ot->poll = ED_operator_object_active_editable;
}
-#endif /* WITH_MOD_FLUID */
+void FLUID_OT_bake_particles(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Bake Particles";
+ ot->description = "Bake Fluid Particles";
+ ot->idname = FLUID_JOB_BAKE_PARTICLES;
-/***************************** Operators ******************************/
+ /* api callbacks */
+ ot->exec = fluid_bake_exec;
+ ot->invoke = fluid_bake_invoke;
+ ot->modal = fluid_bake_modal;
+ ot->poll = ED_operator_object_active_editable;
+}
-static int fluid_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+void FLUID_OT_free_particles(wmOperatorType *ot)
{
- /* only one bake job at a time */
- if (WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_SIM_FLUID)) {
- return OPERATOR_CANCELLED;
- }
+ /* identifiers */
+ ot->name = "Free Particles";
+ ot->description = "Free Fluid Particles";
+ ot->idname = FLUID_JOB_FREE_PARTICLES;
- if (!fluidsimBake(C, op->reports, ED_object_context(C), true)) {
- return OPERATOR_CANCELLED;
- }
+ /* api callbacks */
+ ot->exec = fluid_free_exec;
+ ot->poll = ED_operator_object_active_editable;
+}
- return OPERATOR_FINISHED;
+void FLUID_OT_bake_guides(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Bake Guides";
+ ot->description = "Bake Fluid Guiding";
+ ot->idname = FLUID_JOB_BAKE_GUIDES;
+
+ /* api callbacks */
+ ot->exec = fluid_bake_exec;
+ ot->invoke = fluid_bake_invoke;
+ ot->modal = fluid_bake_modal;
+ ot->poll = ED_operator_object_active_editable;
}
-static int fluid_bake_exec(bContext *C, wmOperator *op)
+void FLUID_OT_free_guides(wmOperatorType *ot)
{
- if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), false)) {
- return OPERATOR_CANCELLED;
- }
+ /* identifiers */
+ ot->name = "Free Guides";
+ ot->description = "Free Fluid Guiding";
+ ot->idname = FLUID_JOB_FREE_GUIDES;
- return OPERATOR_FINISHED;
+ /* api callbacks */
+ ot->exec = fluid_free_exec;
+ ot->poll = ED_operator_object_active_editable;
}
-void FLUID_OT_bake(wmOperatorType *ot)
+void FLUID_OT_pause_bake(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Fluid Simulation Bake";
- ot->description = "Bake fluid simulation";
- ot->idname = "FLUID_OT_bake";
+ ot->name = "Pause Bake";
+ ot->description = "Pause Bake";
+ ot->idname = FLUID_JOB_BAKE_PAUSE;
/* api callbacks */
- ot->invoke = fluid_bake_invoke;
- ot->exec = fluid_bake_exec;
+ ot->exec = fluid_pause_exec;
ot->poll = ED_operator_object_active_editable;
}
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index fc2f3d21bb6..3af818b3a9d 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -103,7 +103,19 @@ void BOID_OT_state_move_up(struct wmOperatorType *ot);
void BOID_OT_state_move_down(struct wmOperatorType *ot);
/* physics_fluid.c */
-void FLUID_OT_bake(struct wmOperatorType *ot);
+void FLUID_OT_bake_all(struct wmOperatorType *ot);
+void FLUID_OT_free_all(struct wmOperatorType *ot);
+void FLUID_OT_bake_data(struct wmOperatorType *ot);
+void FLUID_OT_free_data(struct wmOperatorType *ot);
+void FLUID_OT_bake_noise(struct wmOperatorType *ot);
+void FLUID_OT_free_noise(struct wmOperatorType *ot);
+void FLUID_OT_bake_mesh(struct wmOperatorType *ot);
+void FLUID_OT_free_mesh(struct wmOperatorType *ot);
+void FLUID_OT_bake_particles(struct wmOperatorType *ot);
+void FLUID_OT_free_particles(struct wmOperatorType *ot);
+void FLUID_OT_bake_guides(struct wmOperatorType *ot);
+void FLUID_OT_free_guides(struct wmOperatorType *ot);
+void FLUID_OT_pause_bake(struct wmOperatorType *ot);
/* dynamicpaint.c */
void DPAINT_OT_bake(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index b1b3927d05e..d1536733b9b 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -126,7 +126,19 @@ static void operatortypes_boids(void)
static void operatortypes_fluid(void)
{
- WM_operatortype_append(FLUID_OT_bake);
+ WM_operatortype_append(FLUID_OT_bake_all);
+ WM_operatortype_append(FLUID_OT_free_all);
+ WM_operatortype_append(FLUID_OT_bake_data);
+ WM_operatortype_append(FLUID_OT_free_data);
+ WM_operatortype_append(FLUID_OT_bake_noise);
+ WM_operatortype_append(FLUID_OT_free_noise);
+ WM_operatortype_append(FLUID_OT_bake_mesh);
+ WM_operatortype_append(FLUID_OT_free_mesh);
+ WM_operatortype_append(FLUID_OT_bake_particles);
+ WM_operatortype_append(FLUID_OT_free_particles);
+ WM_operatortype_append(FLUID_OT_bake_guides);
+ WM_operatortype_append(FLUID_OT_free_guides);
+ WM_operatortype_append(FLUID_OT_pause_bake);
}
/**************************** point cache **********************************/
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 9975c49dc54..7c47f7439ab 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -4229,19 +4229,6 @@ static void SCREEN_OT_region_context_menu(wmOperatorType *ot)
* Animation Step.
* \{ */
-static int match_area_with_refresh(int spacetype, int refresh)
-{
- switch (spacetype) {
- case SPACE_TIME:
- if (refresh & SPACE_TIME) {
- return 1;
- }
- break;
- }
-
- return 0;
-}
-
static int match_region_with_redraws(int spacetype,
int regiontype,
int redraws,
@@ -4524,10 +4511,6 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
}
}
-
- if (match_area_with_refresh(sa->spacetype, sad->refresh)) {
- ED_area_tag_refresh(sa);
- }
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 06d79b8a49d..7f71110b360 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -1560,9 +1560,9 @@ static void paint_2d_canvas_free(ImagePaintState *s)
}
}
-static void paint_2d_transform_mouse(ImagePaintState *s, const float in[2], float out[2])
+static void paint_2d_transform_mouse(View2D *v2d, const float in[2], float out[2])
{
- UI_view2d_region_to_view(s->v2d, in[0], in[1], &out[0], &out[1]);
+ UI_view2d_region_to_view(v2d, in[0], in[1], &out[0], &out[1]);
}
static bool is_inside_tile(const int size[2], const float pos[2], const float brush[2])
@@ -1656,8 +1656,9 @@ void paint_2d_stroke(void *ps,
brush_painter_2d_refresh_cache(s, painter, tile, new_coord, mval, pressure, distance, size);
- if (paint_2d_op(s, tile, old_coord, new_coord))
+ if (paint_2d_op(s, tile, old_coord, new_coord)) {
tile->need_redraw = true;
+ }
}
painter->firsttouch = 0;
@@ -1899,14 +1900,24 @@ void paint_2d_bucket_fill(const bContext *C,
return;
}
+ View2D *v2d = s ? s->v2d : &CTX_wm_region(C)->v2d;
float uv_origin[2];
float image_init[2];
- paint_2d_transform_mouse(s, mouse_init, image_init);
+ paint_2d_transform_mouse(v2d, mouse_init, image_init);
int tile_number = BKE_image_get_tile_from_pos(ima, image_init, image_init, uv_origin);
- ImageUser *iuser = paint_2d_get_tile_iuser(s, tile_number);
- if (!iuser) {
- return;
+
+ ImageUser local_iuser, *iuser;
+ if (s != NULL) {
+ iuser = paint_2d_get_tile_iuser(s, tile_number);
+ if (iuser == NULL) {
+ return;
+ }
+ }
+ else {
+ iuser = &local_iuser;
+ BKE_imageuser_default(iuser);
+ iuser->tile = tile_number;
}
ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
@@ -2125,8 +2136,8 @@ void paint_2d_gradient_fill(
return;
}
- paint_2d_transform_mouse(s, mouse_final, image_final);
- paint_2d_transform_mouse(s, mouse_init, image_init);
+ paint_2d_transform_mouse(s->v2d, mouse_final, image_final);
+ paint_2d_transform_mouse(s->v2d, mouse_init, image_init);
sub_v2_v2(image_init, uv_origin);
sub_v2_v2(image_final, uv_origin);
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 8cb0a3f3c86..ecd2b5a3697 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -770,7 +770,6 @@ const char *buttons_context_dir[] = {
"cloth",
"soft_body",
"fluid",
- "smoke",
"collision",
"brush",
"dynamic_paint",
@@ -1018,24 +1017,14 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
return 1;
}
}
- else if (CTX_data_equals(member, "fluid")) {
- PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
- if (ptr && ptr->data) {
- Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
- CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
- return 1;
- }
- }
-
- else if (CTX_data_equals(member, "smoke")) {
+ else if (CTX_data_equals(member, "fluid")) {
PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
if (ptr && ptr->data) {
Object *ob = ptr->data;
- ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
- CTX_data_pointer_set(result, &ob->id, &RNA_SmokeModifier, md);
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid);
+ CTX_data_pointer_set(result, &ob->id, &RNA_FluidModifier, md);
return 1;
}
}
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 9a633427d82..3f563fe9033 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -549,12 +549,15 @@ static void draw_udim_label(ARegion *ar, float fx, float fy, const char *label)
int textwidth = BLF_width(blf_mono_font, label, strlen(label)) + 10;
float stepx = BLI_rcti_size_x(&ar->v2d.mask) / BLI_rctf_size_x(&ar->v2d.cur);
float opacity;
- if (textwidth < 0.5f * (stepx - 10))
+ if (textwidth < 0.5f * (stepx - 10)) {
opacity = 1.0f;
- else if (textwidth < (stepx - 10))
+ }
+ else if (textwidth < (stepx - 10)) {
opacity = 2.0f - 2.0f * (textwidth / (stepx - 10));
- else
+ }
+ else {
opacity = 0.0f;
+ }
BLF_color4ub(blf_mono_font, 220, 220, 220, 150 * opacity);
BLF_position(blf_mono_font, (int)(x + 10), (int)(y + 10), 0);
BLF_draw_ascii(blf_mono_font, label, strlen(label));
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index c0c66a28ad9..c1172b0cea8 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -4419,7 +4419,7 @@ static void tile_fill_draw(bContext *UNUSED(C), wmOperator *op)
void IMAGE_OT_tile_fill(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Fill tile";
+ ot->name = "Fill Tile";
ot->description = "Fill the current tile with a generated image";
ot->idname = "IMAGE_OT_tile_fill";
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 9a6f685f5fc..17088b0e2b4 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -2125,14 +2125,14 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case eModifierType_Surface:
data.icon = ICON_MOD_PHYSICS;
break;
- case eModifierType_Fluidsim:
+ case eModifierType_Fluidsim: /* deprecated, old fluid modifier */
data.icon = ICON_MOD_FLUIDSIM;
break;
case eModifierType_Multires:
data.icon = ICON_MOD_MULTIRES;
break;
- case eModifierType_Smoke:
- data.icon = ICON_MOD_SMOKE;
+ case eModifierType_Fluid:
+ data.icon = ICON_MOD_FLUID;
break;
case eModifierType_Solidify:
data.icon = ICON_MOD_SOLIDIFY;
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 2feef9e0c9a..95d7f79f666 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -32,7 +32,7 @@ set(INC
../../windowmanager
../../../../intern/glew-mx
../../../../intern/guardedalloc
- ../../../../intern/smoke/extern
+ ../../../../intern/mantaflow/extern
# dna_type_offsets.h
${CMAKE_CURRENT_BINARY_DIR}/../../makesdna/intern
@@ -95,8 +95,8 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
-if(WITH_MOD_SMOKE)
- add_definitions(-DWITH_SMOKE)
+if(WITH_MOD_FLUID)
+ add_definitions(-DWITH_FLUID)
endif()
blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
index 848accb8534..f761a44fe16 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
@@ -70,19 +70,17 @@ static bool WIDGETGROUP_tool_generic_poll(const bContext *C, wmGizmoGroupType *g
static wmGizmo *tool_generic_create_gizmo(const bContext *C, wmGizmoGroup *gzgroup)
{
- wmGizmo *gz;
+ wmGizmo *gz = WM_gizmo_new("GIZMO_GT_button_2d", gzgroup, NULL);
+ gz->flag |= WM_GIZMO_OPERATOR_TOOL_INIT;
- if (gzgroup->type->idname == handle_normal_id) {
- gz = WM_gizmo_new("GIZMO_GT_button_2d", gzgroup, NULL);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
+ UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
- unit_m4(gz->matrix_offset);
+ unit_m4(gz->matrix_offset);
- PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
- RNA_property_enum_set(gz->ptr, prop, ICON_NONE);
+ RNA_enum_set(gz->ptr, "icon", ICON_NONE);
+ if (gzgroup->type->idname == handle_normal_id) {
gz->scale_basis = 0.12f;
gz->matrix_offset[3][2] -= 12.0;
RNA_enum_set(gz->ptr,
@@ -91,17 +89,8 @@ static wmGizmo *tool_generic_create_gizmo(const bContext *C, wmGizmoGroup *gzgro
ED_GIZMO_BUTTON_SHOW_OUTLINE));
}
else {
- gz = WM_gizmo_new("GIZMO_GT_button_2d", gzgroup, NULL);
-
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
- UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
-
- unit_m4(gz->matrix_offset);
gz->scale_basis = 0.16f * 3;
- PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
- RNA_property_enum_set(gz->ptr, prop, ICON_NONE);
-
RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_BACKDROP);
/* Make the center low alpha. */
diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h
index f9f6a513f63..a188e2eb829 100644
--- a/source/blender/editors/transform/transform_snap.h
+++ b/source/blender/editors/transform/transform_snap.h
@@ -26,6 +26,8 @@
/* For enum. */
#include "DNA_space_types.h"
+struct SnapObjectParams;
+
bool peelObjectsTransform(struct TransInfo *t,
const float mval[2],
const bool use_peel_object,
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index 44335f4da25..87743911add 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -30,7 +30,6 @@ set(INC
../makesdna
../makesrna
../render/extern/include
- ../../../intern/elbeem/extern
../../../intern/eigen
../../../intern/guardedalloc
)
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
index c71d074e564..bc545ce6ce8 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
@@ -1,6 +1,4 @@
/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -17,12 +15,9 @@
*
* The Original Code is Copyright (C) 2017, Blender Foundation
* This is a new part of Blender
- *
- * ***** END GPL LICENSE BLOCK *****
- *
*/
-/** \file blender/gpencil_modifiers/intern/MOD_gpencilstrokes.c
+/** \file
* \ingroup modifiers
*/
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index bcdc1550fd2..8daeda67c80 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -44,7 +44,7 @@ set(INC
../../../intern/glew-mx
../../../intern/guardedalloc
- ../../../intern/smoke/extern
+ ../../../intern/mantaflow/extern
)
set(INC_SYS
@@ -61,6 +61,7 @@ set(SRC
intern/gpu_context.cpp
intern/gpu_debug.c
intern/gpu_draw.c
+ intern/gpu_draw_smoke.c
intern/gpu_element.c
intern/gpu_extensions.c
intern/gpu_framebuffer.c
@@ -319,8 +320,8 @@ data_to_c_simple(shaders/gpu_shader_cfg_world_clip_lib.glsl SRC)
data_to_c_simple(shaders/gpu_shader_common_obinfos_lib.glsl SRC)
-if(WITH_MOD_SMOKE)
- add_definitions(-DWITH_SMOKE)
+if(WITH_MOD_FLUID)
+ add_definitions(-DWITH_FLUID)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 6d2b0ad3be3..2ed4ee44287 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -31,12 +31,12 @@ struct CCGElem;
struct CCGKey;
struct DMFlagMat;
struct GSet;
-struct Mesh;
struct MLoop;
struct MLoopCol;
struct MLoopTri;
struct MPoly;
struct MVert;
+struct Mesh;
struct PBVH;
/* Buffers for drawing from PBVH grids. */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 7814c723fec..f89a76cf49c 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -28,11 +28,11 @@
extern "C" {
#endif
+struct FluidModifierData;
struct ImBuf;
struct Image;
struct ImageUser;
struct Main;
-struct SmokeModifierData;
#include "DNA_object_enums.h"
@@ -83,12 +83,12 @@ void GPU_free_images(struct Main *bmain);
void GPU_free_images_anim(struct Main *bmain);
void GPU_free_images_old(struct Main *bmain);
-/* smoke drawing functions */
-void GPU_free_smoke(struct SmokeModifierData *smd);
-void GPU_free_smoke_velocity(struct SmokeModifierData *smd);
-void GPU_create_smoke(struct SmokeModifierData *smd, int highres);
-void GPU_create_smoke_coba_field(struct SmokeModifierData *smd);
-void GPU_create_smoke_velocity(struct SmokeModifierData *smd);
+/* gpu_draw_smoke.c */
+void GPU_free_smoke(struct FluidModifierData *mmd);
+void GPU_free_smoke_velocity(struct FluidModifierData *mmd);
+void GPU_create_smoke(struct FluidModifierData *mmd, int highres);
+void GPU_create_smoke_coba_field(struct FluidModifierData *mmd);
+void GPU_create_smoke_velocity(struct FluidModifierData *mmd);
/* Delayed free of OpenGL buffers by main thread */
void GPU_free_unused_buffers(struct Main *bmain);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 23ea9a62ef8..ca804a26acd 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -2131,8 +2131,10 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
static int count_active_texture_sampler(GPUShader *shader, char *source)
{
char *code = source;
- int samplers_id[64]; /* Remember this is per stage. */
- int sampler_len = 0;
+
+ /* Remember this is per stage. */
+ GSet *sampler_ids = BLI_gset_int_new(__func__);
+ int num_samplers = 0;
while ((code = strstr(code, "uniform "))) {
/* Move past "uniform". */
@@ -2167,22 +2169,16 @@ static int count_active_texture_sampler(GPUShader *shader, char *source)
continue;
}
/* Catch duplicates. */
- bool is_duplicate = false;
- for (int i = 0; i < sampler_len; i++) {
- if (samplers_id[i] == id) {
- is_duplicate = true;
- }
- }
-
- if (!is_duplicate) {
- samplers_id[sampler_len] = id;
- sampler_len++;
+ if (BLI_gset_add(sampler_ids, POINTER_FROM_INT(id))) {
+ num_samplers++;
}
}
}
}
- return sampler_len;
+ BLI_gset_free(sampler_ids, NULL);
+
+ return num_samplers;
}
static bool gpu_pass_shader_validate(GPUPass *pass, GPUShader *shader)
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index d698db45b7a..95738bb1a95 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -36,17 +36,9 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "DNA_light_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_smoke_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_particle_types.h"
+#include "DNA_image_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_userdef_types.h"
#include "MEM_guardedalloc.h"
@@ -54,14 +46,10 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#include "BKE_colorband.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
-#include "BKE_material.h"
#include "BKE_movieclip.h"
-#include "BKE_node.h"
-#include "BKE_scene.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
@@ -71,10 +59,6 @@
#include "PIL_time.h"
-#ifdef WITH_SMOKE
-# include "smoke_API.h"
-#endif
-
static void gpu_free_image_immediate(Image *ima);
//* Checking powers of two for images since OpenGL ES requires it */
@@ -940,372 +924,6 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
BKE_image_release_ibuf(ima, ibuf, NULL);
}
-/* *************************** Transfer functions *************************** */
-
-enum {
- TFUNC_FLAME_SPECTRUM = 0,
- TFUNC_COLOR_RAMP = 1,
-};
-
-#define TFUNC_WIDTH 256
-
-#ifdef WITH_SMOKE
-static void create_flame_spectrum_texture(float *data)
-{
-# define FIRE_THRESH 7
-# define MAX_FIRE_ALPHA 0.06f
-# define FULL_ON_FIRE 100
-
- float *spec_pixels = MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
-
- blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000);
-
- for (int i = 0; i < 16; i++) {
- for (int j = 0; j < 16; j++) {
- for (int k = 0; k < TFUNC_WIDTH; k++) {
- int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4;
- if (k >= FIRE_THRESH) {
- spec_pixels[index] = (data[k * 4]);
- spec_pixels[index + 1] = (data[k * 4 + 1]);
- spec_pixels[index + 2] = (data[k * 4 + 2]);
- spec_pixels[index + 3] = MAX_FIRE_ALPHA *
- ((k > FULL_ON_FIRE) ?
- 1.0f :
- (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
- }
- else {
- zero_v4(&spec_pixels[index]);
- }
- }
- }
- }
-
- memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH);
-
- MEM_freeN(spec_pixels);
-
-# undef FIRE_THRESH
-# undef MAX_FIRE_ALPHA
-# undef FULL_ON_FIRE
-}
-
-static void create_color_ramp(const ColorBand *coba, float *data)
-{
- for (int i = 0; i < TFUNC_WIDTH; i++) {
- BKE_colorband_evaluate(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
- }
-}
-
-static GPUTexture *create_transfer_function(int type, const ColorBand *coba)
-{
- float *data = MEM_mallocN(sizeof(float) * 4 * TFUNC_WIDTH, __func__);
-
- switch (type) {
- case TFUNC_FLAME_SPECTRUM:
- create_flame_spectrum_texture(data);
- break;
- case TFUNC_COLOR_RAMP:
- create_color_ramp(coba, data);
- break;
- }
-
- GPUTexture *tex = GPU_texture_create_1d(TFUNC_WIDTH, GPU_RGBA8, data, NULL);
-
- MEM_freeN(data);
-
- return tex;
-}
-
-static void swizzle_texture_channel_rrrr(GPUTexture *tex)
-{
- GPU_texture_bind(tex, 0);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
- GPU_texture_unbind(tex);
-}
-
-static GPUTexture *create_field_texture(SmokeDomainSettings *sds)
-{
- float *field = NULL;
-
- switch (sds->coba_field) {
- case FLUID_FIELD_DENSITY:
- field = smoke_get_density(sds->fluid);
- break;
- case FLUID_FIELD_HEAT:
- field = smoke_get_heat(sds->fluid);
- break;
- case FLUID_FIELD_FUEL:
- field = smoke_get_fuel(sds->fluid);
- break;
- case FLUID_FIELD_REACT:
- field = smoke_get_react(sds->fluid);
- break;
- case FLUID_FIELD_FLAME:
- field = smoke_get_flame(sds->fluid);
- break;
- case FLUID_FIELD_VELOCITY_X:
- field = smoke_get_velocity_x(sds->fluid);
- break;
- case FLUID_FIELD_VELOCITY_Y:
- field = smoke_get_velocity_y(sds->fluid);
- break;
- case FLUID_FIELD_VELOCITY_Z:
- field = smoke_get_velocity_z(sds->fluid);
- break;
- case FLUID_FIELD_COLOR_R:
- field = smoke_get_color_r(sds->fluid);
- break;
- case FLUID_FIELD_COLOR_G:
- field = smoke_get_color_g(sds->fluid);
- break;
- case FLUID_FIELD_COLOR_B:
- field = smoke_get_color_b(sds->fluid);
- break;
- case FLUID_FIELD_FORCE_X:
- field = smoke_get_force_x(sds->fluid);
- break;
- case FLUID_FIELD_FORCE_Y:
- field = smoke_get_force_y(sds->fluid);
- break;
- case FLUID_FIELD_FORCE_Z:
- field = smoke_get_force_z(sds->fluid);
- break;
- default:
- return NULL;
- }
-
- GPUTexture *tex = GPU_texture_create_nD(
- sds->res[0], sds->res[1], sds->res[2], 3, field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
-
- swizzle_texture_channel_rrrr(tex);
- return tex;
-}
-
-static GPUTexture *create_density_texture(SmokeDomainSettings *sds, int highres)
-{
- float *data = NULL, *source;
- int cell_count = (highres) ? smoke_turbulence_get_cells(sds->wt) : sds->total_cells;
- const bool has_color = (highres) ? smoke_turbulence_has_colors(sds->wt) :
- smoke_has_colors(sds->fluid);
- int *dim = (highres) ? sds->res_wt : sds->res;
- eGPUTextureFormat format = (has_color) ? GPU_RGBA8 : GPU_R8;
-
- if (has_color) {
- data = MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture");
- }
-
- if (highres) {
- if (has_color) {
- smoke_turbulence_get_rgba(sds->wt, data, 0);
- }
- else {
- source = smoke_turbulence_get_density(sds->wt);
- }
- }
- else {
- if (has_color) {
- smoke_get_rgba(sds->fluid, data, 0);
- }
- else {
- source = smoke_get_density(sds->fluid);
- }
- }
-
- GPUTexture *tex = GPU_texture_create_nD(dim[0],
- dim[1],
- dim[2],
- 3,
- (has_color) ? data : source,
- format,
- GPU_DATA_FLOAT,
- 0,
- true,
- NULL);
- if (data) {
- MEM_freeN(data);
- }
-
- if (format == GPU_R8) {
- /* Swizzle the RGBA components to read the Red channel so
- * that the shader stay the same for colored and non color
- * density textures. */
- swizzle_texture_channel_rrrr(tex);
- }
- return tex;
-}
-
-static GPUTexture *create_flame_texture(SmokeDomainSettings *sds, int highres)
-{
- float *source = NULL;
- const bool has_fuel = (highres) ? smoke_turbulence_has_fuel(sds->wt) :
- smoke_has_fuel(sds->fluid);
- int *dim = (highres) ? sds->res_wt : sds->res;
-
- if (!has_fuel) {
- return NULL;
- }
-
- if (highres) {
- source = smoke_turbulence_get_flame(sds->wt);
- }
- else {
- source = smoke_get_flame(sds->fluid);
- }
-
- GPUTexture *tex = GPU_texture_create_nD(
- dim[0], dim[1], dim[2], 3, source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
-
- swizzle_texture_channel_rrrr(tex);
-
- return tex;
-}
-#endif /* WITH_SMOKE */
-
-void GPU_free_smoke(SmokeModifierData *smd)
-{
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
- if (smd->domain->tex) {
- GPU_texture_free(smd->domain->tex);
- }
- smd->domain->tex = NULL;
-
- if (smd->domain->tex_shadow) {
- GPU_texture_free(smd->domain->tex_shadow);
- }
- smd->domain->tex_shadow = NULL;
-
- if (smd->domain->tex_flame) {
- GPU_texture_free(smd->domain->tex_flame);
- }
- smd->domain->tex_flame = NULL;
-
- if (smd->domain->tex_flame_coba) {
- GPU_texture_free(smd->domain->tex_flame_coba);
- }
- smd->domain->tex_flame_coba = NULL;
-
- if (smd->domain->tex_coba) {
- GPU_texture_free(smd->domain->tex_coba);
- }
- smd->domain->tex_coba = NULL;
-
- if (smd->domain->tex_field) {
- GPU_texture_free(smd->domain->tex_field);
- }
- smd->domain->tex_field = NULL;
- }
-}
-
-void GPU_create_smoke_coba_field(SmokeModifierData *smd)
-{
-#ifdef WITH_SMOKE
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- SmokeDomainSettings *sds = smd->domain;
-
- if (!sds->tex_field) {
- sds->tex_field = create_field_texture(sds);
- }
- if (!sds->tex_coba) {
- sds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, sds->coba);
- }
- }
-#else // WITH_SMOKE
- smd->domain->tex_field = NULL;
-#endif // WITH_SMOKE
-}
-
-void GPU_create_smoke(SmokeModifierData *smd, int highres)
-{
-#ifdef WITH_SMOKE
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- SmokeDomainSettings *sds = smd->domain;
-
- if (!sds->tex) {
- sds->tex = create_density_texture(sds, highres);
- }
- if (!sds->tex_flame) {
- sds->tex_flame = create_flame_texture(sds, highres);
- }
- if (!sds->tex_flame_coba && sds->tex_flame) {
- sds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL);
- }
- if (!sds->tex_shadow) {
- sds->tex_shadow = GPU_texture_create_nD(sds->res[0],
- sds->res[1],
- sds->res[2],
- 3,
- sds->shadow,
- GPU_R8,
- GPU_DATA_FLOAT,
- 0,
- true,
- NULL);
- }
- }
-#else // WITH_SMOKE
- (void)highres;
- smd->domain->tex = NULL;
- smd->domain->tex_flame = NULL;
- smd->domain->tex_flame_coba = NULL;
- smd->domain->tex_shadow = NULL;
-#endif // WITH_SMOKE
-}
-
-void GPU_create_smoke_velocity(SmokeModifierData *smd)
-{
-#ifdef WITH_SMOKE
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- SmokeDomainSettings *sds = smd->domain;
-
- const float *vel_x = smoke_get_velocity_x(sds->fluid);
- const float *vel_y = smoke_get_velocity_y(sds->fluid);
- const float *vel_z = smoke_get_velocity_z(sds->fluid);
-
- if (ELEM(NULL, vel_x, vel_y, vel_z)) {
- return;
- }
-
- if (!sds->tex_velocity_x) {
- sds->tex_velocity_x = GPU_texture_create_3d(
- sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_x, NULL);
- sds->tex_velocity_y = GPU_texture_create_3d(
- sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_y, NULL);
- sds->tex_velocity_z = GPU_texture_create_3d(
- sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_z, NULL);
- }
- }
-#else // WITH_SMOKE
- smd->domain->tex_velocity_x = NULL;
- smd->domain->tex_velocity_y = NULL;
- smd->domain->tex_velocity_z = NULL;
-#endif // WITH_SMOKE
-}
-
-/* TODO Unify with the other GPU_free_smoke. */
-void GPU_free_smoke_velocity(SmokeModifierData *smd)
-{
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
- if (smd->domain->tex_velocity_x) {
- GPU_texture_free(smd->domain->tex_velocity_x);
- }
-
- if (smd->domain->tex_velocity_y) {
- GPU_texture_free(smd->domain->tex_velocity_y);
- }
-
- if (smd->domain->tex_velocity_z) {
- GPU_texture_free(smd->domain->tex_velocity_z);
- }
-
- smd->domain->tex_velocity_x = NULL;
- smd->domain->tex_velocity_y = NULL;
- smd->domain->tex_velocity_z = NULL;
- }
-}
-
static LinkNode *image_free_queue = NULL;
static ThreadMutex img_queue_mutex = BLI_MUTEX_INITIALIZER;
diff --git a/source/blender/gpu/intern/gpu_draw_smoke.c b/source/blender/gpu/intern/gpu_draw_smoke.c
new file mode 100644
index 00000000000..5cca472148a
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_draw_smoke.c
@@ -0,0 +1,416 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * GPU fluid drawing functions.
+ */
+
+#include <string.h>
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_fluid_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_colorband.h"
+
+#include "GPU_draw.h"
+#include "GPU_glew.h"
+#include "GPU_texture.h"
+
+#ifdef WITH_FLUID
+# include "manta_fluid_API.h"
+#endif
+
+/* -------------------------------------------------------------------- */
+/** \name Private API
+ * \{ */
+
+#ifdef WITH_FLUID
+
+enum {
+ TFUNC_FLAME_SPECTRUM = 0,
+ TFUNC_COLOR_RAMP = 1,
+};
+
+# define TFUNC_WIDTH 256
+
+static void create_flame_spectrum_texture(float *data)
+{
+# define FIRE_THRESH 7
+# define MAX_FIRE_ALPHA 0.06f
+# define FULL_ON_FIRE 100
+
+ float *spec_pixels = MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
+
+ blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000);
+
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < 16; j++) {
+ for (int k = 0; k < TFUNC_WIDTH; k++) {
+ int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4;
+ if (k >= FIRE_THRESH) {
+ spec_pixels[index] = (data[k * 4]);
+ spec_pixels[index + 1] = (data[k * 4 + 1]);
+ spec_pixels[index + 2] = (data[k * 4 + 2]);
+ spec_pixels[index + 3] = MAX_FIRE_ALPHA *
+ ((k > FULL_ON_FIRE) ?
+ 1.0f :
+ (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
+ }
+ else {
+ zero_v4(&spec_pixels[index]);
+ }
+ }
+ }
+ }
+
+ memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH);
+
+ MEM_freeN(spec_pixels);
+
+# undef FIRE_THRESH
+# undef MAX_FIRE_ALPHA
+# undef FULL_ON_FIRE
+}
+
+static void create_color_ramp(const struct ColorBand *coba, float *data)
+{
+ for (int i = 0; i < TFUNC_WIDTH; i++) {
+ BKE_colorband_evaluate(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
+ }
+}
+
+static GPUTexture *create_transfer_function(int type, const struct ColorBand *coba)
+{
+ float *data = MEM_mallocN(sizeof(float) * 4 * TFUNC_WIDTH, __func__);
+
+ switch (type) {
+ case TFUNC_FLAME_SPECTRUM:
+ create_flame_spectrum_texture(data);
+ break;
+ case TFUNC_COLOR_RAMP:
+ create_color_ramp(coba, data);
+ break;
+ }
+
+ GPUTexture *tex = GPU_texture_create_1d(TFUNC_WIDTH, GPU_RGBA8, data, NULL);
+
+ MEM_freeN(data);
+
+ return tex;
+}
+
+static void swizzle_texture_channel_rrrr(GPUTexture *tex)
+{
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
+ GPU_texture_unbind(tex);
+}
+
+static GPUTexture *create_field_texture(FluidDomainSettings *mds)
+{
+ float *field = NULL;
+
+ switch (mds->coba_field) {
+ case FLUID_DOMAIN_FIELD_DENSITY:
+ field = manta_smoke_get_density(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_HEAT:
+ field = manta_smoke_get_heat(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_FUEL:
+ field = manta_smoke_get_fuel(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_REACT:
+ field = manta_smoke_get_react(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_FLAME:
+ field = manta_smoke_get_flame(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_VELOCITY_X:
+ field = manta_get_velocity_x(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_VELOCITY_Y:
+ field = manta_get_velocity_y(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_VELOCITY_Z:
+ field = manta_get_velocity_z(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_COLOR_R:
+ field = manta_smoke_get_color_r(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_COLOR_G:
+ field = manta_smoke_get_color_g(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_COLOR_B:
+ field = manta_smoke_get_color_b(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_FORCE_X:
+ field = manta_get_force_x(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_FORCE_Y:
+ field = manta_get_force_y(mds->fluid);
+ break;
+ case FLUID_DOMAIN_FIELD_FORCE_Z:
+ field = manta_get_force_z(mds->fluid);
+ break;
+ default:
+ return NULL;
+ }
+
+ GPUTexture *tex = GPU_texture_create_nD(
+ mds->res[0], mds->res[1], mds->res[2], 3, field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
+
+ swizzle_texture_channel_rrrr(tex);
+ return tex;
+}
+
+static GPUTexture *create_density_texture(FluidDomainSettings *mds, int highres)
+{
+ float *data = NULL, *source;
+ int cell_count = (highres) ? manta_smoke_turbulence_get_cells(mds->fluid) : mds->total_cells;
+ const bool has_color = (highres) ? manta_smoke_turbulence_has_colors(mds->fluid) :
+ manta_smoke_has_colors(mds->fluid);
+ int *dim = (highres) ? mds->res_noise : mds->res;
+ eGPUTextureFormat format = (has_color) ? GPU_RGBA8 : GPU_R8;
+
+ if (has_color) {
+ data = MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture");
+ }
+
+ if (highres) {
+ if (has_color) {
+ manta_smoke_turbulence_get_rgba(mds->fluid, data, 0);
+ }
+ else {
+ source = manta_smoke_turbulence_get_density(mds->fluid);
+ }
+ }
+ else {
+ if (has_color) {
+ manta_smoke_get_rgba(mds->fluid, data, 0);
+ }
+ else {
+ source = manta_smoke_get_density(mds->fluid);
+ }
+ }
+
+ GPUTexture *tex = GPU_texture_create_nD(dim[0],
+ dim[1],
+ dim[2],
+ 3,
+ (has_color) ? data : source,
+ format,
+ GPU_DATA_FLOAT,
+ 0,
+ true,
+ NULL);
+ if (data) {
+ MEM_freeN(data);
+ }
+
+ if (format == GPU_R8) {
+ /* Swizzle the RGBA components to read the Red channel so
+ * that the shader stay the same for colored and non color
+ * density textures. */
+ swizzle_texture_channel_rrrr(tex);
+ }
+ return tex;
+}
+
+static GPUTexture *create_flame_texture(FluidDomainSettings *mds, int highres)
+{
+ float *source = NULL;
+ const bool has_fuel = (highres) ? manta_smoke_turbulence_has_fuel(mds->fluid) :
+ manta_smoke_has_fuel(mds->fluid);
+ int *dim = (highres) ? mds->res_noise : mds->res;
+
+ if (!has_fuel) {
+ return NULL;
+ }
+
+ if (highres) {
+ source = manta_smoke_turbulence_get_flame(mds->fluid);
+ }
+ else {
+ source = manta_smoke_get_flame(mds->fluid);
+ }
+
+ GPUTexture *tex = GPU_texture_create_nD(
+ dim[0], dim[1], dim[2], 3, source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
+
+ swizzle_texture_channel_rrrr(tex);
+
+ return tex;
+}
+
+#endif /* WITH_FLUID */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public API
+ * \{ */
+
+void GPU_free_smoke(FluidModifierData *mmd)
+{
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN && mmd->domain) {
+ if (mmd->domain->tex) {
+ GPU_texture_free(mmd->domain->tex);
+ }
+ mmd->domain->tex = NULL;
+
+ if (mmd->domain->tex_shadow) {
+ GPU_texture_free(mmd->domain->tex_shadow);
+ }
+ mmd->domain->tex_shadow = NULL;
+
+ if (mmd->domain->tex_flame) {
+ GPU_texture_free(mmd->domain->tex_flame);
+ }
+ mmd->domain->tex_flame = NULL;
+
+ if (mmd->domain->tex_flame_coba) {
+ GPU_texture_free(mmd->domain->tex_flame_coba);
+ }
+ mmd->domain->tex_flame_coba = NULL;
+
+ if (mmd->domain->tex_coba) {
+ GPU_texture_free(mmd->domain->tex_coba);
+ }
+ mmd->domain->tex_coba = NULL;
+
+ if (mmd->domain->tex_field) {
+ GPU_texture_free(mmd->domain->tex_field);
+ }
+ mmd->domain->tex_field = NULL;
+ }
+}
+
+void GPU_create_smoke_coba_field(FluidModifierData *mmd)
+{
+#ifndef WITH_FLUID
+ UNUSED_VARS(mmd);
+#else
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ FluidDomainSettings *mds = mmd->domain;
+
+ if (!mds->tex_field) {
+ mds->tex_field = create_field_texture(mds);
+ }
+ if (!mds->tex_coba) {
+ mds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, mds->coba);
+ }
+ }
+#endif
+}
+
+void GPU_create_smoke(FluidModifierData *mmd, int highres)
+{
+#ifndef WITH_FLUID
+ UNUSED_VARS(mmd, highres);
+#else
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ FluidDomainSettings *mds = mmd->domain;
+
+ if (!mds->tex) {
+ mds->tex = create_density_texture(mds, highres);
+ }
+ if (!mds->tex_flame) {
+ mds->tex_flame = create_flame_texture(mds, highres);
+ }
+ if (!mds->tex_flame_coba && mds->tex_flame) {
+ mds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL);
+ }
+ if (!mds->tex_shadow) {
+ mds->tex_shadow = GPU_texture_create_nD(mds->res[0],
+ mds->res[1],
+ mds->res[2],
+ 3,
+ manta_smoke_get_shadow(mds->fluid),
+ GPU_R8,
+ GPU_DATA_FLOAT,
+ 0,
+ true,
+ NULL);
+ }
+ }
+#endif /* WITH_FLUID */
+}
+
+void GPU_create_smoke_velocity(FluidModifierData *mmd)
+{
+#ifndef WITH_FLUID
+ UNUSED_VARS(mmd);
+#else
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN) {
+ FluidDomainSettings *mds = mmd->domain;
+
+ const float *vel_x = manta_get_velocity_x(mds->fluid);
+ const float *vel_y = manta_get_velocity_y(mds->fluid);
+ const float *vel_z = manta_get_velocity_z(mds->fluid);
+
+ if (ELEM(NULL, vel_x, vel_y, vel_z)) {
+ return;
+ }
+
+ if (!mds->tex_velocity_x) {
+ mds->tex_velocity_x = GPU_texture_create_3d(
+ mds->res[0], mds->res[1], mds->res[2], GPU_R16F, vel_x, NULL);
+ mds->tex_velocity_y = GPU_texture_create_3d(
+ mds->res[0], mds->res[1], mds->res[2], GPU_R16F, vel_y, NULL);
+ mds->tex_velocity_z = GPU_texture_create_3d(
+ mds->res[0], mds->res[1], mds->res[2], GPU_R16F, vel_z, NULL);
+ }
+ }
+#endif /* WITH_FLUID */
+}
+
+/* TODO Unify with the other GPU_free_smoke. */
+void GPU_free_smoke_velocity(FluidModifierData *mmd)
+{
+ if (mmd->type & MOD_FLUID_TYPE_DOMAIN && mmd->domain) {
+ if (mmd->domain->tex_velocity_x) {
+ GPU_texture_free(mmd->domain->tex_velocity_x);
+ }
+
+ if (mmd->domain->tex_velocity_y) {
+ GPU_texture_free(mmd->domain->tex_velocity_y);
+ }
+
+ if (mmd->domain->tex_velocity_z) {
+ GPU_texture_free(mmd->domain->tex_velocity_z);
+ }
+
+ mmd->domain->tex_velocity_x = NULL;
+ mmd->domain->tex_velocity_y = NULL;
+ mmd->domain->tex_velocity_z = NULL;
+ }
+}
+
+/** \} */
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 4ead3165715..354344328d3 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -182,7 +182,7 @@ typedef enum eArmature_DeformFlag {
ARM_DEF_VGROUP = (1 << 0),
ARM_DEF_ENVELOPE = (1 << 1),
ARM_DEF_QUATERNION = (1 << 2),
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
ARM_DEF_B_BONE_REST = (1 << 3), /* deprecated */
#endif
ARM_DEF_INVERT_VGROUP = (1 << 4),
@@ -190,7 +190,7 @@ typedef enum eArmature_DeformFlag {
/* armature->pathflag */
// XXX deprecated... old animation system (armature only viz)
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
typedef enum eArmature_PathFlag {
ARM_PATH_FNUMS = (1 << 0),
ARM_PATH_KFRAS = (1 << 1),
@@ -228,7 +228,7 @@ typedef enum eBone_Flag {
BONE_UNKEYED = (1 << 13),
/** set to prevent hinge child bones from influencing the transform center */
BONE_HINGE_CHILD_TRANSFORM = (1 << 14),
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
/** No parent scale */
BONE_NO_SCALE = (1 << 15),
#endif
diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h
index b78b2f64648..7c7d4bc182e 100644
--- a/source/blender/makesdna/DNA_camera_types.h
+++ b/source/blender/makesdna/DNA_camera_types.h
@@ -156,7 +156,7 @@ enum {
CAM_SHOWNAME = (1 << 4),
CAM_ANGLETOGGLE = (1 << 5),
CAM_DS_EXPAND = (1 << 6),
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
CAM_PANORAMA = (1 << 7), /* deprecated */
#endif
CAM_SHOWSENSOR = (1 << 8),
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index d7b392d5133..0baa11c3059 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -755,7 +755,7 @@ typedef enum eCopyRotation_Flags {
ROTLIKE_X_INVERT = (1 << 4),
ROTLIKE_Y_INVERT = (1 << 5),
ROTLIKE_Z_INVERT = (1 << 6),
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
ROTLIKE_OFFSET = (1 << 7),
#endif
} eCopyRotation_Flags;
@@ -976,7 +976,7 @@ typedef enum eSplineIK_Flags {
CONSTRAINT_SPLINEIK_BOUND = (1 << 0),
/* root of chain is not influenced by the constraint */
CONSTRAINT_SPLINEIK_NO_ROOT = (1 << 1),
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
/* bones in the chain should not scale to fit the curve */
CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1 << 2),
#endif
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 0a6423d569f..f70dc19616b 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -97,7 +97,7 @@ typedef enum CustomDataType {
CD_AUTO_FROM_NAME = -1,
CD_MVERT = 0,
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
CD_MSTICKY = 1, /* DEPRECATED */
#endif
CD_MDEFORMVERT = 2,
@@ -113,7 +113,7 @@ typedef enum CustomDataType {
CD_PROP_STR = 12,
CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
CD_ORCO = 14, /* undeformed vertex coordinates, normalized to 0..1 range */
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
CD_MTEXPOLY = 15, /* deprecated */
#endif
CD_MLOOPUV = 16,
diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h
new file mode 100644
index 00000000000..e12bee13ebc
--- /dev/null
+++ b/source/blender/makesdna/DNA_fluid_types.h
@@ -0,0 +1,590 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup DNA
+ */
+
+#ifndef __DNA_FLUID_TYPES_H__
+#define __DNA_FLUID_TYPES_H__
+
+/* Domain flags. */
+enum {
+ FLUID_DOMAIN_USE_NOISE = (1 << 1), /* Use noise. */
+ FLUID_DOMAIN_USE_DISSOLVE = (1 << 2), /* Let smoke dissolve. */
+ FLUID_DOMAIN_USE_DISSOLVE_LOG = (1 << 3), /* Using 1/x for dissolve. */
+
+#ifdef DNA_DEPRECATED_ALLOW
+ FLUID_DOMAIN_USE_HIGH_SMOOTH = (1 << 5), /* -- Deprecated -- */
+#endif
+ FLUID_DOMAIN_FILE_LOAD = (1 << 6), /* Flag for file load. */
+ FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN = (1 << 7),
+ FLUID_DOMAIN_USE_ADAPTIVE_TIME = (1 << 8), /* Adaptive time stepping in domain. */
+ FLUID_DOMAIN_USE_MESH = (1 << 9), /* Use mesh. */
+ FLUID_DOMAIN_USE_GUIDE = (1 << 10), /* Use guiding. */
+ FLUID_DOMAIN_USE_SPEED_VECTORS = (1 << 11), /* Generate mesh speed vectors. */
+ FLUID_DOMAIN_EXPORT_MANTA_SCRIPT = (1 << 12), /* Export mantaflow script during bake. */
+ FLUID_DOMAIN_USE_FRACTIONS = (1 << 13), /* Use second order obstacles. */
+};
+
+/* Border collisions. */
+enum {
+ FLUID_DOMAIN_BORDER_FRONT = (1 << 1),
+ FLUID_DOMAIN_BORDER_BACK = (1 << 2),
+ FLUID_DOMAIN_BORDER_RIGHT = (1 << 3),
+ FLUID_DOMAIN_BORDER_LEFT = (1 << 4),
+ FLUID_DOMAIN_BORDER_TOP = (1 << 5),
+ FLUID_DOMAIN_BORDER_BOTTOM = (1 << 6),
+};
+
+/* Cache file formats. */
+enum {
+ FLUID_DOMAIN_FILE_UNI = (1 << 0),
+ FLUID_DOMAIN_FILE_OPENVDB = (1 << 1),
+ FLUID_DOMAIN_FILE_RAW = (1 << 2),
+ FLUID_DOMAIN_FILE_OBJECT = (1 << 3),
+ FLUID_DOMAIN_FILE_BIN_OBJECT = (1 << 4),
+};
+
+/* Slice method. */
+enum {
+ FLUID_DOMAIN_SLICE_VIEW_ALIGNED = 0,
+ FLUID_DOMAIN_SLICE_AXIS_ALIGNED = 1,
+};
+
+/* Axis aligned method. */
+enum {
+ AXIS_SLICE_FULL = 0,
+ AXIS_SLICE_SINGLE = 1,
+};
+
+/* Single slice direction. */
+enum {
+ SLICE_AXIS_AUTO = 0,
+ SLICE_AXIS_X = 1,
+ SLICE_AXIS_Y = 2,
+ SLICE_AXIS_Z = 3,
+};
+
+/* Axis aligned method. */
+enum {
+ VOLUME_INTERP_LINEAR = 0,
+ VOLUME_INTERP_CUBIC = 1,
+};
+
+enum {
+ VECTOR_DRAW_NEEDLE = 0,
+ VECTOR_DRAW_STREAMLINE = 1,
+};
+
+enum {
+ SNDPARTICLE_BOUNDARY_DELETE = 0,
+ SNDPARTICLE_BOUNDARY_PUSHOUT = 1,
+};
+
+enum {
+ SNDPARTICLE_COMBINED_EXPORT_OFF = 0,
+ SNDPARTICLE_COMBINED_EXPORT_SPRAY_FOAM = 1,
+ SNDPARTICLE_COMBINED_EXPORT_SPRAY_BUBBLE = 2,
+ SNDPARTICLE_COMBINED_EXPORT_FOAM_BUBBLE = 3,
+ SNDPARTICLE_COMBINED_EXPORT_SPRAY_FOAM_BUBBLE = 4,
+};
+
+enum {
+ FLUID_DOMAIN_FIELD_DENSITY = 0,
+ FLUID_DOMAIN_FIELD_HEAT = 1,
+ FLUID_DOMAIN_FIELD_FUEL = 2,
+ FLUID_DOMAIN_FIELD_REACT = 3,
+ FLUID_DOMAIN_FIELD_FLAME = 4,
+ FLUID_DOMAIN_FIELD_VELOCITY_X = 5,
+ FLUID_DOMAIN_FIELD_VELOCITY_Y = 6,
+ FLUID_DOMAIN_FIELD_VELOCITY_Z = 7,
+ FLUID_DOMAIN_FIELD_COLOR_R = 8,
+ FLUID_DOMAIN_FIELD_COLOR_G = 9,
+ FLUID_DOMAIN_FIELD_COLOR_B = 10,
+ FLUID_DOMAIN_FIELD_FORCE_X = 11,
+ FLUID_DOMAIN_FIELD_FORCE_Y = 12,
+ FLUID_DOMAIN_FIELD_FORCE_Z = 13,
+};
+
+/* Fluid domain types. */
+enum {
+ FLUID_DOMAIN_TYPE_GAS = 0,
+ FLUID_DOMAIN_TYPE_LIQUID = 1,
+};
+
+/* Smoke noise types. */
+enum {
+ FLUID_NOISE_TYPE_WAVELET = (1 << 0),
+};
+
+/* Mesh levelset generator types. */
+enum {
+ FLUID_DOMAIN_MESH_IMPROVED = 0,
+ FLUID_DOMAIN_MESH_UNION = 1,
+};
+
+/* Guiding velocity source. */
+enum {
+ FLUID_DOMAIN_GUIDE_SRC_DOMAIN = 0,
+ FLUID_DOMAIN_GUIDE_SRC_EFFECTOR = 1,
+};
+
+/* Fluid data fields (active_fields). */
+enum {
+ FLUID_DOMAIN_ACTIVE_HEAT = (1 << 0),
+ FLUID_DOMAIN_ACTIVE_FIRE = (1 << 1),
+ FLUID_DOMAIN_ACTIVE_COLORS = (1 << 2),
+ FLUID_DOMAIN_ACTIVE_COLOR_SET = (1 << 3),
+ FLUID_DOMAIN_ACTIVE_OBSTACLE = (1 << 4),
+ FLUID_DOMAIN_ACTIVE_GUIDE = (1 << 5),
+ FLUID_DOMAIN_ACTIVE_INVEL = (1 << 6),
+ FLUID_DOMAIN_ACTIVE_OUTFLOW = (1 << 7),
+};
+
+/* Particle types. */
+enum {
+ FLUID_DOMAIN_PARTICLE_FLIP = (1 << 0),
+ FLUID_DOMAIN_PARTICLE_SPRAY = (1 << 1),
+ FLUID_DOMAIN_PARTICLE_BUBBLE = (1 << 2),
+ FLUID_DOMAIN_PARTICLE_FOAM = (1 << 3),
+ FLUID_DOMAIN_PARTICLE_TRACER = (1 << 4),
+};
+
+/* Liquid simulation methods. */
+enum {
+ FLUID_DOMAIN_METHOD_FLIP = (1 << 0),
+ FLUID_DOMAIN_METHOD_APIC = (1 << 1),
+};
+
+/* Cache options. */
+enum {
+ FLUID_DOMAIN_BAKING_DATA = (1 << 0),
+ FLUID_DOMAIN_BAKED_DATA = (1 << 1),
+ FLUID_DOMAIN_BAKING_NOISE = (1 << 2),
+ FLUID_DOMAIN_BAKED_NOISE = (1 << 3),
+ FLUID_DOMAIN_BAKING_MESH = (1 << 4),
+ FLUID_DOMAIN_BAKED_MESH = (1 << 5),
+ FLUID_DOMAIN_BAKING_PARTICLES = (1 << 6),
+ FLUID_DOMAIN_BAKED_PARTICLES = (1 << 7),
+ FLUID_DOMAIN_BAKING_GUIDE = (1 << 8),
+ FLUID_DOMAIN_BAKED_GUIDE = (1 << 9),
+ FLUID_DOMAIN_OUTDATED_DATA = (1 << 10),
+ FLUID_DOMAIN_OUTDATED_NOISE = (1 << 11),
+ FLUID_DOMAIN_OUTDATED_MESH = (1 << 12),
+ FLUID_DOMAIN_OUTDATED_PARTICLES = (1 << 13),
+ FLUID_DOMAIN_OUTDATED_GUIDE = (1 << 14),
+};
+
+#define FLUID_DOMAIN_BAKING_ALL \
+ (FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKING_NOISE | FLUID_DOMAIN_BAKING_MESH | \
+ FLUID_DOMAIN_BAKING_PARTICLES | FLUID_DOMAIN_BAKING_GUIDE)
+
+#define FLUID_DOMAIN_BAKED_ALL \
+ (FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_BAKED_MESH | \
+ FLUID_DOMAIN_BAKED_PARTICLES | FLUID_DOMAIN_BAKED_GUIDE)
+
+#define FLUID_DOMAIN_DIR_DEFAULT "cache_fluid"
+#define FLUID_DOMAIN_DIR_CONFIG "config"
+#define FLUID_DOMAIN_DIR_DATA "data"
+#define FLUID_DOMAIN_DIR_NOISE "noise"
+#define FLUID_DOMAIN_DIR_MESH "mesh"
+#define FLUID_DOMAIN_DIR_PARTICLES "particles"
+#define FLUID_DOMAIN_DIR_GUIDE "guiding"
+#define FLUID_DOMAIN_DIR_SCRIPT "script"
+#define FLUID_DOMAIN_SMOKE_SCRIPT "smoke_script.py"
+#define FLUID_DOMAIN_LIQUID_SCRIPT "liquid_script.py"
+
+enum {
+ FLUID_DOMAIN_CACHE_REPLAY = 0,
+ FLUID_DOMAIN_CACHE_MODULAR = 1,
+ FLUID_DOMAIN_CACHE_FINAL = 2,
+};
+
+/* Deprecated values (i.e. all defines and enums below this line up until typedefs). */
+/* Cache compression. */
+enum {
+ SM_CACHE_LIGHT = 0,
+ SM_CACHE_HEAVY = 1,
+};
+
+/* High resolution sampling types. */
+enum {
+ SM_HRES_NEAREST = 0,
+ SM_HRES_LINEAR = 1,
+ SM_HRES_FULLSAMPLE = 2,
+};
+
+enum {
+ VDB_COMPRESSION_BLOSC = 0,
+ VDB_COMPRESSION_ZIP = 1,
+ VDB_COMPRESSION_NONE = 2,
+};
+
+typedef struct FluidDomainVertexVelocity {
+ float vel[3];
+} FluidDomainVertexVelocity;
+
+typedef struct FluidDomainSettings {
+
+ /* -- Runtime-only fields (from here on). -- */
+
+ struct FluidModifierData *mmd; /* For fast RNA access. */
+ struct MANTA *fluid;
+ struct MANTA *fluid_old; /* Adaptive domain needs access to old fluid state. */
+ void *fluid_mutex;
+ struct Collection *fluid_group;
+ struct Collection *force_group; /* UNUSED */
+ struct Collection *effector_group; /* Effector objects group. */
+ struct GPUTexture *tex;
+ struct GPUTexture *tex_wt;
+ struct GPUTexture *tex_shadow;
+ struct GPUTexture *tex_flame;
+ struct GPUTexture *tex_flame_coba;
+ struct GPUTexture *tex_coba;
+ struct GPUTexture *tex_field;
+ struct GPUTexture *tex_velocity_x;
+ struct GPUTexture *tex_velocity_y;
+ struct GPUTexture *tex_velocity_z;
+ struct Object *guide_parent;
+ /** Vertex velocities of simulated fluid mesh. */
+ struct FluidDomainVertexVelocity *mesh_velocities;
+ struct EffectorWeights *effector_weights;
+
+ /* Domain object data. */
+ float p0[3]; /* Start point of BB in local space
+ * (includes sub-cell shift for adaptive domain). */
+ float p1[3]; /* End point of BB in local space. */
+ float dp0[3]; /* Difference from object center to grid start point. */
+ float cell_size[3]; /* Size of simulation cell in local space. */
+ float global_size[3]; /* Global size of domain axises. */
+ float prev_loc[3];
+ int shift[3]; /* Current domain shift in simulation cells. */
+ float shift_f[3]; /* Exact domain shift. */
+ float obj_shift_f[3]; /* How much object has shifted since previous smoke frame (used to "lock"
+ * domain while drawing). */
+ float imat[4][4]; /* Domain object imat. */
+ float obmat[4][4]; /* Domain obmat. */
+ float fluidmat[4][4]; /* Low res fluid matrix. */
+ float fluidmat_wt[4][4]; /* High res fluid matrix. */
+ int base_res[3]; /* Initial "non-adapted" resolution. */
+ int res_min[3]; /* Cell min. */
+ int res_max[3]; /* Cell max. */
+ int res[3]; /* Data resolution (res_max-res_min). */
+ int total_cells;
+ float dx; /* 1.0f / res. */
+ float scale; /* Largest domain size. */
+ int boundary_width; /* Usually this is just 1. */
+
+ /* -- User-accesible fields (from here on). -- */
+
+ /* Adaptive domain options. */
+ int adapt_margin;
+ int adapt_res;
+ float adapt_threshold;
+ char _pad1[4]; /* Unused. */
+
+ /* Fluid domain options */
+ int maxres; /* Longest axis on the BB gets this resolution assigned. */
+ int solver_res; /* Dimension of manta solver, 2d or 3d. */
+ int border_collisions; /* How domain border collisions are handled. */
+ int flags; /* Use-mesh, use-noise, etc. */
+ float gravity[3];
+ int active_fields;
+ short type; /* Gas, liquid. */
+ char _pad2[6]; /* Unused. */
+
+ /* Smoke domain options. */
+ float alpha;
+ float beta;
+ int diss_speed; /* In frames. */
+ float vorticity;
+ float active_color[3]; /* Monitor smoke color. */
+ int highres_sampling;
+
+ /* Flame options. */
+ float burning_rate, flame_smoke, flame_vorticity;
+ float flame_ignition, flame_max_temp;
+ float flame_smoke_color[3];
+
+ /* Noise options. */
+ float noise_strength;
+ float noise_pos_scale;
+ float noise_time_anim;
+ int res_noise[3];
+ int noise_scale;
+ short noise_type; /* Noise type: wave, curl, anisotropic. */
+ char _pad3[2]; /* Unused. */
+
+ /* Liquid domain options. */
+ float particle_randomness;
+ int particle_number;
+ int particle_minimum;
+ int particle_maximum;
+ float particle_radius;
+ float particle_band_width;
+ float fractions_threshold;
+ float flip_ratio;
+ short simulation_method;
+ char _pad4[6];
+
+ /* Diffusion options. */
+ float surface_tension;
+ float viscosity_base;
+ int viscosity_exponent;
+ float domain_size;
+
+ /* Mesh options. */
+ float mesh_concave_upper;
+ float mesh_concave_lower;
+ float mesh_particle_radius;
+ int mesh_smoothen_pos;
+ int mesh_smoothen_neg;
+ int mesh_scale;
+ int totvert;
+ short mesh_generator;
+ char _pad5[2]; /* Unused. */
+
+ /* Secondary particle options. */
+ int particle_type;
+ int particle_scale;
+ float sndparticle_tau_min_wc;
+ float sndparticle_tau_max_wc;
+ float sndparticle_tau_min_ta;
+ float sndparticle_tau_max_ta;
+ float sndparticle_tau_min_k;
+ float sndparticle_tau_max_k;
+ int sndparticle_k_wc;
+ int sndparticle_k_ta;
+ float sndparticle_k_b;
+ float sndparticle_k_d;
+ float sndparticle_l_min;
+ float sndparticle_l_max;
+ int sndparticle_potential_radius;
+ int sndparticle_update_radius;
+ char sndparticle_boundary;
+ char sndparticle_combined_export;
+ char _pad6[6]; /* Unused. */
+
+ /* Fluid guiding options. */
+ float guide_alpha; /* Guiding weight scalar (determines strength). */
+ int guide_beta; /* Guiding blur radius (affects size of vortices). */
+ float guide_vel_factor; /* Multiply guiding velocity by this factor. */
+ int guide_res[3]; /* Res for velocity guide grids - independent from base res. */
+ short guide_source;
+ char _pad7[2]; /* Unused. */
+
+ /* Cache options. */
+ int cache_frame_start;
+ int cache_frame_end;
+ int cache_frame_pause_data;
+ int cache_frame_pause_noise;
+ int cache_frame_pause_mesh;
+ int cache_frame_pause_particles;
+ int cache_frame_pause_guide;
+ int cache_flag;
+ char cache_mesh_format;
+ char cache_data_format;
+ char cache_particle_format;
+ char cache_noise_format;
+ char cache_directory[1024];
+ char error[64]; /* Bake error description. */
+ short cache_type;
+ char _pad8[2]; /* Unused. */
+
+ /* Time options. */
+ float dt;
+ float time_total;
+ float time_per_frame;
+ float frame_length;
+ float time_scale;
+ float cfl_condition;
+ int timesteps_minimum;
+ int timesteps_maximum;
+
+ /* Display options. */
+ char slice_method, axis_slice_method;
+ char slice_axis, draw_velocity;
+ float slice_per_voxel;
+ float slice_depth;
+ float display_thickness;
+ struct ColorBand *coba;
+ float vector_scale;
+ char vector_draw_type;
+ char use_coba;
+ char coba_field; /* Simulation field used for the color mapping. */
+ char interp_method;
+
+ /* -- Deprecated / unsed options (below). -- */
+
+ /* View options. */
+ int viewsettings;
+ char _pad9[4]; /* Unused. */
+
+ /* OpenVDB cache options. */
+ int openvdb_comp;
+ float clipping;
+ char data_depth;
+ char _pad10[7]; /* Unused. */
+
+ /* Pointcache options. */
+ /* Smoke uses only one cache from now on (index [0]), but keeping the array for now for reading
+ * old files. */
+ struct PointCache *point_cache[2]; /* Definition is in DNA_object_force_types.h. */
+ struct ListBase ptcaches[2];
+ int cache_comp;
+ int cache_high_comp;
+ char cache_file_format;
+ char _pad11[7]; /* Unused. */
+
+} FluidDomainSettings;
+
+/* Flow types. */
+enum {
+ FLUID_FLOW_TYPE_SMOKE = 1,
+ FLUID_FLOW_TYPE_FIRE = 2,
+ FLUID_FLOW_TYPE_SMOKEFIRE = 3,
+ FLUID_FLOW_TYPE_LIQUID = 4,
+};
+
+/* Flow behavior types. */
+enum {
+ FLUID_FLOW_BEHAVIOR_INFLOW = 0,
+ FLUID_FLOW_BEHAVIOR_OUTFLOW = 1,
+ FLUID_FLOW_BEHAVIOR_GEOMETRY = 2,
+};
+
+/* Flow source types. */
+enum {
+ FLUID_FLOW_SOURCE_PARTICLES = 0,
+ FLUID_FLOW_SOURCE_MESH = 1,
+};
+
+/* Flow texture types. */
+enum {
+ FLUID_FLOW_TEXTURE_MAP_AUTO = 0,
+ FLUID_FLOW_TEXTURE_MAP_UV = 1,
+};
+
+/* Flow flags. */
+enum {
+ /* Old style emission. */
+ FLUID_FLOW_ABSOLUTE = (1 << 1),
+ /* Passes particles speed to the smoke. */
+ FLUID_FLOW_INITVELOCITY = (1 << 2),
+ /* Use texture to control emission speed. */
+ FLUID_FLOW_TEXTUREEMIT = (1 << 3),
+ /* Use specific size for particles instead of closest cell. */
+ FLUID_FLOW_USE_PART_SIZE = (1 << 4),
+ /* Control when to apply inflow. */
+ FLUID_FLOW_USE_INFLOW = (1 << 5),
+ /* Control when to apply inflow. */
+ FLUID_FLOW_USE_PLANE_INIT = (1 << 6),
+};
+
+typedef struct FluidFlowSettings {
+
+ /* -- Runtime-only fields (from here on). -- */
+
+ /* For fast RNA access. */
+ struct FluidModifierData *mmd;
+ struct Mesh *mesh;
+ struct ParticleSystem *psys;
+ struct Tex *noise_texture;
+
+ /* Initial velocity. */
+ /* Previous vertex positions in domain space. */
+ float *verts_old;
+ int numverts;
+ float vel_multi; /* Multiplier for inherited velocity. */
+ float vel_normal;
+ float vel_random;
+ float vel_coord[3];
+ char _pad1[4];
+
+ /* -- User-accesible fields (from here on). -- */
+
+ /* Emission. */
+ float density;
+ float color[3];
+ float fuel_amount;
+ /* Delta temperature (temp - ambient temp). */
+ float temperature;
+ /* Density emitted within mesh volume. */
+ float volume_density;
+ /* Maximum emission distance from mesh surface. */
+ float surface_distance;
+ float particle_size;
+ int subframes;
+
+ /* Texture control. */
+ float texture_size;
+ float texture_offset;
+ char _pad2[4];
+ /* MAX_CUSTOMDATA_LAYER_NAME. */
+ char uvlayer_name[64];
+ short vgroup_density;
+
+ short type; /* Smoke, flames, both, outflow, liquid. */
+ short behavior; /* Inflow, outflow, static. */
+ short source;
+ short texture_type;
+ short _pad3[3];
+ int flags; /* Absolute emission etc. */
+} FluidFlowSettings;
+
+/* Effector types. */
+enum {
+ FLUID_EFFECTOR_TYPE_COLLISION = 0,
+ FLUID_EFFECTOR_TYPE_GUIDE = 1,
+};
+
+/* Guiding velocity modes. */
+enum {
+ FLUID_EFFECTOR_GUIDE_MAX = 0,
+ FLUID_EFFECTOR_GUIDE_MIN = 1,
+ FLUID_EFFECTOR_GUIDE_OVERRIDE = 2,
+ FLUID_EFFECTOR_GUIDE_AVERAGED = 3,
+};
+
+/* Collision objects (filled with smoke). */
+typedef struct FluidEffectorSettings {
+
+ /* -- Runtime-only fields (from here on). -- */
+
+ /* For fast RNA access. */
+ struct FluidModifierData *mmd;
+ struct Mesh *mesh;
+ float *verts_old;
+ int numverts;
+
+ /* -- User-accesible fields (from here on). -- */
+
+ float surface_distance; /* Thickness of mesh surface, used in obstacle sdf. */
+ int flags;
+ short type;
+ char _pad1[2];
+
+ /* Guiding options. */
+ float vel_multi; /* Multiplier for object velocity. */
+ short guide_mode;
+ char _pad2[2];
+} FluidEffectorSettings;
+
+#endif
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index e975d7acd74..1c58d03a1a8 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -184,7 +184,7 @@ typedef struct Image {
enum {
IMA_FLAG_UNUSED_0 = (1 << 0), /* cleared */
IMA_FLAG_UNUSED_1 = (1 << 1), /* cleared */
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
IMA_DO_PREMUL = (1 << 2),
#endif
IMA_FLAG_UNUSED_4 = (1 << 4), /* cleared */
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 60e0eb2976e..86ea22690ee 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -204,7 +204,7 @@ typedef struct Mesh {
} Mesh;
/* deprecated by MTFace, only here for file reading */
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
typedef struct TFace {
/** The faces image for the active UVLayer. */
void *tpage;
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 44bf275d422..52e12dc4057 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -62,7 +62,9 @@ typedef enum ModifierType {
eModifierType_SimpleDeform = 28,
eModifierType_Multires = 29,
eModifierType_Surface = 30,
+#ifdef DNA_DEPRECATED_ALLOW
eModifierType_Smoke = 31,
+#endif
eModifierType_ShapeKey = 32,
eModifierType_Solidify = 33,
eModifierType_Screw = 34,
@@ -87,10 +89,11 @@ typedef enum ModifierType {
eModifierType_SurfaceDeform = 53,
eModifierType_WeightedNormal = 54,
eModifierType_Weld = 55,
- eModifierType_FunctionPoints = 56,
+ eModifierType_Fluid = 56,
eModifierType_BParticles = 57,
eModifierType_BParticlesOutput = 58,
eModifierType_FunctionDeform = 59,
+ eModifierType_FunctionPoints = 58,
NUM_MODIFIER_TYPES,
} ModifierType;
@@ -455,24 +458,24 @@ enum {
MOD_BEVEL_VMESH_CUTOFF,
};
-typedef struct SmokeModifierData {
+typedef struct FluidModifierData {
ModifierData modifier;
- struct SmokeDomainSettings *domain;
+ struct FluidDomainSettings *domain;
/** Inflow, outflow, smoke objects. */
- struct SmokeFlowSettings *flow;
- /** Collision objects. */
- struct SmokeCollSettings *coll;
+ struct FluidFlowSettings *flow;
+ /** Effector objects (collision, guiding). */
+ struct FluidEffectorSettings *effector;
float time;
/** Domain, inflow, outflow, .... */
int type;
-} SmokeModifierData;
+} FluidModifierData;
-/* Smoke modifier flags */
+/* Fluid modifier flags */
enum {
- MOD_SMOKE_TYPE_DOMAIN = (1 << 0),
- MOD_SMOKE_TYPE_FLOW = (1 << 1),
- MOD_SMOKE_TYPE_COLL = (1 << 2),
+ MOD_FLUID_TYPE_DOMAIN = (1 << 0),
+ MOD_FLUID_TYPE_FLOW = (1 << 1),
+ MOD_FLUID_TYPE_EFFEC = (1 << 2),
};
typedef struct DisplaceModifierData {
@@ -981,6 +984,7 @@ typedef enum {
eMultiresModifierFlag_UseCrease = (1 << 2),
} MultiresModifierFlag;
+/* DEPRECATED, only used for versioning. */
typedef struct FluidsimModifierData {
ModifierData modifier;
@@ -988,6 +992,11 @@ typedef struct FluidsimModifierData {
struct FluidsimSettings *fss;
} FluidsimModifierData;
+/* DEPRECATED, only used for versioning. */
+typedef struct SmokeModifierData {
+ ModifierData modifier;
+} SmokeModifierData;
+
typedef struct ShrinkwrapModifierData {
ModifierData modifier;
@@ -1152,7 +1161,7 @@ enum {
MOD_SOLIDIFY_EVEN = (1 << 1),
MOD_SOLIDIFY_NORMAL_CALC = (1 << 2),
MOD_SOLIDIFY_VGROUP_INV = (1 << 3),
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
MOD_SOLIDIFY_RIM_MATERIAL = (1 << 4), /* deprecated, used in do_versions */
#endif
MOD_SOLIDIFY_FLIP = (1 << 5),
@@ -1599,7 +1608,7 @@ typedef struct TriangulateModifierData {
/* TriangulateModifierData.flag */
enum {
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
MOD_TRIANGULATE_BEAUTY = (1 << 0), /* deprecated */
#endif
MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS = 1 << 1,
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index d94a05ccb81..22202717b0c 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1284,7 +1284,7 @@ enum {
/* subsurface */
enum {
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
SHD_SUBSURFACE_COMPATIBLE = 0, // Deprecated
#endif
SHD_SUBSURFACE_CUBIC = 1,
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index a1ea51ab573..fbed0754046 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -371,7 +371,8 @@ typedef struct Object {
struct Collection *instance_collection;
/** If fluidsim enabled, store additional settings. */
- struct FluidsimSettings *fluidsimSettings;
+ struct FluidsimSettings *fluidsimSettings
+ DNA_DEPRECATED; // XXX deprecated... replaced by mantaflow, keep for readfile
struct DerivedMesh *derivedDeform, *derivedFinal;
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 4aaa1fe32f6..8bbbc9fc85d 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -273,7 +273,7 @@ typedef struct ParticleSettings {
struct Collection *instance_collection;
struct ListBase instance_weights;
- struct Collection *eff_group DNA_DEPRECATED; // deprecated
+ struct Collection *force_group DNA_DEPRECATED; // deprecated
struct Object *instance_object;
struct Object *bb_ob;
/** Old animation system, deprecated for 2.5. */
@@ -406,7 +406,7 @@ typedef enum eParticleDrawFlag {
PART_DRAW_VEL = (1 << 0),
PART_DRAW_GLOBAL_OB = (1 << 1),
PART_DRAW_SIZE = (1 << 2),
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
/** Render emitter as well. */
PART_DRAW_EMITTER = (1 << 3), /* DEPRECATED */
#endif
@@ -429,13 +429,33 @@ typedef enum eParticleDrawFlag {
PART_DRAW_HAIR_GRID = (1 << 18),
} eParticleDrawFlag;
-/* part->type */
-/* hair is always baked static in object/geometry space */
-/* other types (normal particles) are in global space and not static baked */
-#define PART_EMITTER 0
-//#define PART_REACTOR 1
-#define PART_HAIR 2
-#define PART_FLUID 3
+/* part->type
+ * Hair is always baked static in object/geometry space.
+ * Other types (normal particles) are in global space and not static baked. */
+enum {
+ PART_EMITTER = (1 << 0),
+ /* REACTOR type currently unused */
+ /* PART_REACTOR = (1 << 1), */
+ PART_HAIR = (1 << 2),
+ PART_FLUID = (1 << 3), /* deprecated (belonged to elbeem) */
+ PART_FLUID_FLIP = (1 << 4),
+ PART_FLUID_SPRAY = (1 << 5),
+ PART_FLUID_BUBBLE = (1 << 6),
+ PART_FLUID_FOAM = (1 << 7),
+ PART_FLUID_TRACER = (1 << 8),
+};
+
+/* Mirroring Mantaflow particle types from particle.h (Mantaflow header). */
+enum {
+ PARTICLE_TYPE_NONE = (0 << 0),
+ PARTICLE_TYPE_NEW = (1 << 0),
+ PARTICLE_TYPE_SPRAY = (1 << 1),
+ PARTICLE_TYPE_BUBBLE = (1 << 2),
+ PARTICLE_TYPE_FOAM = (1 << 3),
+ PARTICLE_TYPE_TRACER = (1 << 4),
+ PARTICLE_TYPE_DELETE = (1 << 10),
+ PARTICLE_TYPE_INVALID = (1 << 30),
+};
/* part->flag */
#define PART_REACT_STA_END 1
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 980fbfa72e0..7cfd19b4bd9 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -101,7 +101,7 @@ typedef struct AviCodecData {
typedef enum eFFMpegPreset {
FFM_PRESET_NONE,
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
/* Previously used by h.264 to control encoding speed vs. file size. */
FFM_PRESET_ULTRAFAST, /* DEPRECATED */
FFM_PRESET_SUPERFAST, /* DEPRECATED */
@@ -1929,7 +1929,7 @@ enum {
R_COLOR_MANAGEMENT_UNUSED_1 = (1 << 1),
};
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
/* RenderData.subimtype flag options for imtype */
enum {
R_OPENEXR_HALF = (1 << 0), /*deprecated*/
@@ -2169,7 +2169,7 @@ typedef enum eVGroupSelect {
/* FFMpegCodecData.flags */
enum {
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
FFMPEG_MULTIPLEX_AUDIO = (1 << 0), /* deprecated, you can choose none as audiocodec now */
#endif
FFMPEG_AUTOSPLIT_OUTPUT = (1 << 1),
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
deleted file mode 100644
index d795800df2f..00000000000
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2006 by NaN Holding BV.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup DNA
- */
-
-#ifndef __DNA_SMOKE_TYPES_H__
-#define __DNA_SMOKE_TYPES_H__
-
-/* flags */
-enum {
- MOD_SMOKE_HIGHRES = (1 << 1), /* enable high resolution */
- MOD_SMOKE_DISSOLVE = (1 << 2), /* let smoke dissolve */
- MOD_SMOKE_DISSOLVE_LOG = (1 << 3), /* using 1/x for dissolve */
-
-#ifdef DNA_DEPRECATED
- MOD_SMOKE_HIGH_SMOOTH = (1 << 5), /* -- Deprecated -- */
-#endif
- MOD_SMOKE_FILE_LOAD = (1 << 6), /* flag for file load */
- MOD_SMOKE_ADAPTIVE_DOMAIN = (1 << 7),
-};
-
-/* noise */
-#define MOD_SMOKE_NOISEWAVE (1 << 0)
-#define MOD_SMOKE_NOISEFFT (1 << 1)
-#define MOD_SMOKE_NOISECURL (1 << 2)
-/* viewsettings */
-#define MOD_SMOKE_VIEW_SHOW_HIGHRES (1 << 0)
-
-/* slice method */
-enum {
- MOD_SMOKE_SLICE_VIEW_ALIGNED = 0,
- MOD_SMOKE_SLICE_AXIS_ALIGNED = 1,
-};
-
-/* axis aligned method */
-enum {
- AXIS_SLICE_FULL = 0,
- AXIS_SLICE_SINGLE = 1,
-};
-
-/* single slice direction */
-enum {
- SLICE_AXIS_AUTO = 0,
- SLICE_AXIS_X = 1,
- SLICE_AXIS_Y = 2,
- SLICE_AXIS_Z = 3,
-};
-
-/* axis aligned method */
-enum {
- VOLUME_INTERP_LINEAR = 0,
- VOLUME_INTERP_CUBIC = 1,
-};
-
-enum {
- VECTOR_DRAW_NEEDLE = 0,
- VECTOR_DRAW_STREAMLINE = 1,
-};
-
-enum {
- FLUID_FIELD_DENSITY = 0,
- FLUID_FIELD_HEAT = 1,
- FLUID_FIELD_FUEL = 2,
- FLUID_FIELD_REACT = 3,
- FLUID_FIELD_FLAME = 4,
- FLUID_FIELD_VELOCITY_X = 5,
- FLUID_FIELD_VELOCITY_Y = 6,
- FLUID_FIELD_VELOCITY_Z = 7,
- FLUID_FIELD_COLOR_R = 8,
- FLUID_FIELD_COLOR_G = 9,
- FLUID_FIELD_COLOR_B = 10,
- FLUID_FIELD_FORCE_X = 11,
- FLUID_FIELD_FORCE_Y = 12,
- FLUID_FIELD_FORCE_Z = 13,
-};
-
-/* cache compression */
-#define SM_CACHE_LIGHT 0
-#define SM_CACHE_HEAVY 1
-
-/* domain border collision */
-#define SM_BORDER_OPEN 0
-#define SM_BORDER_VERTICAL 1
-#define SM_BORDER_CLOSED 2
-
-/* collision types */
-#define SM_COLL_STATIC 0
-#define SM_COLL_RIGID 1
-#define SM_COLL_ANIMATED 2
-
-/* high resolution sampling types */
-#define SM_HRES_NEAREST 0
-#define SM_HRES_LINEAR 1
-#define SM_HRES_FULLSAMPLE 2
-
-/* smoke data fields (active_fields) */
-#define SM_ACTIVE_HEAT (1 << 0)
-#define SM_ACTIVE_FIRE (1 << 1)
-#define SM_ACTIVE_COLORS (1 << 2)
-#define SM_ACTIVE_COLOR_SET (1 << 3)
-
-enum {
- VDB_COMPRESSION_BLOSC = 0,
- VDB_COMPRESSION_ZIP = 1,
- VDB_COMPRESSION_NONE = 2,
-};
-
-typedef struct SmokeDomainSettings {
- /** For fast RNA access. */
- struct SmokeModifierData *smd;
- struct FLUID_3D *fluid;
- void *fluid_mutex;
- struct Collection *fluid_group;
- struct Collection *eff_group; // UNUSED
- struct Collection *coll_group; // collision objects group
- struct WTURBULENCE *wt; // WTURBULENCE object, if active
- struct GPUTexture *tex;
- struct GPUTexture *tex_wt;
- struct GPUTexture *tex_shadow;
- struct GPUTexture *tex_flame;
- struct GPUTexture *tex_flame_coba;
- struct GPUTexture *tex_coba;
- struct GPUTexture *tex_field;
- struct GPUTexture *tex_velocity_x;
- struct GPUTexture *tex_velocity_y;
- struct GPUTexture *tex_velocity_z;
- float *shadow;
-
- /* simulation data */
- /** Start point of BB in local space (includes sub-cell shift for adaptive domain.)*/
- float p0[3];
- /** End point of BB in local space. */
- float p1[3];
- /** Difference from object center to grid start point. */
- float dp0[3];
- /** Size of simulation cell in local space. */
- float cell_size[3];
- /** Global size of domain axises. */
- float global_size[3];
- float prev_loc[3];
- /** Current domain shift in simulation cells. */
- int shift[3];
- /** Exact domain shift. */
- float shift_f[3];
- /**
- * How much object has shifted since previous smoke frame
- * (used to "lock" domain while drawing).
- */
- float obj_shift_f[3];
- /** Domain object imat. */
- float imat[4][4];
- /** Domain obmat. */
- float obmat[4][4];
- /** Low res fluid matrix. */
- float fluidmat[4][4];
- /** High res fluid matrix. */
- float fluidmat_wt[4][4];
-
- /** Initial "non-adapted" resolution. */
- int base_res[3];
- /** Cell min. */
- int res_min[3];
- /** Cell max. */
- int res_max[3];
- /** Data resolution (res_max-res_min). */
- int res[3];
- int total_cells;
- /** 1.0f / res. */
- float dx;
- /** Largest domain size. */
- float scale;
-
- /* user settings */
- int adapt_margin;
- int adapt_res;
- float adapt_threshold;
-
- float alpha;
- float beta;
- /** Wavelet amplification. */
- int amplify;
- /** Longest axis on the BB gets this resolution assigned. */
- int maxres;
- /** Show up-res or low res, etc. */
- int flags;
- int viewsettings;
- /** Noise type: wave, curl, anisotropic. */
- short noise;
- short diss_percent;
- /** In frames. */
- int diss_speed;
- float strength;
- int res_wt[3];
- float dx_wt;
- /* point cache options */
- int cache_comp;
- int cache_high_comp;
- /* OpenVDB cache options */
- int openvdb_comp;
- char cache_file_format;
- char data_depth;
- char _pad[2];
-
- /* Smoke uses only one cache from now on (index [0]),
- * but keeping the array for now for reading old files. */
- /** Definition is in DNA_object_force_types.h. */
- struct PointCache *point_cache[2];
- struct ListBase ptcaches[2];
- struct EffectorWeights *effector_weights;
- /** How domain border collisions are handled. */
- int border_collisions;
- float time_scale;
- float vorticity;
- int active_fields;
- /** Monitor color situation of simulation. */
- float active_color[3];
- int highres_sampling;
-
- /* flame parameters */
- float burning_rate, flame_smoke, flame_vorticity;
- float flame_ignition, flame_max_temp;
- float flame_smoke_color[3];
-
- /* Display settings */
- char slice_method, axis_slice_method;
- char slice_axis, draw_velocity;
- float slice_per_voxel;
- float slice_depth;
- float display_thickness;
-
- struct ColorBand *coba;
- float vector_scale;
- char vector_draw_type;
- char use_coba;
- /** Simulation field used for the color mapping. */
- char coba_field;
- char interp_method;
-
- float clipping;
- char _pad3[4];
-} SmokeDomainSettings;
-
-/* inflow / outflow */
-
-/* type */
-#define MOD_SMOKE_FLOW_TYPE_SMOKE 0
-#define MOD_SMOKE_FLOW_TYPE_FIRE 1
-#define MOD_SMOKE_FLOW_TYPE_OUTFLOW 2
-#define MOD_SMOKE_FLOW_TYPE_SMOKEFIRE 3
-
-/* flow source */
-#define MOD_SMOKE_FLOW_SOURCE_PARTICLES 0
-#define MOD_SMOKE_FLOW_SOURCE_MESH 1
-
-/* flow texture type */
-#define MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO 0
-#define MOD_SMOKE_FLOW_TEXTURE_MAP_UV 1
-
-/* flags */
-enum {
- /** Old style emission. */
- MOD_SMOKE_FLOW_ABSOLUTE = (1 << 1),
- /** Passes particles speed to the smoke. */
- MOD_SMOKE_FLOW_INITVELOCITY = (1 << 2),
- /** Use texture to control emission speed. */
- MOD_SMOKE_FLOW_TEXTUREEMIT = (1 << 3),
- /** Use specific size for particles instead of closest cell. */
- MOD_SMOKE_FLOW_USE_PART_SIZE = (1 << 4),
-};
-
-typedef struct SmokeFlowSettings {
- /** For fast RNA access. */
- struct SmokeModifierData *smd;
- struct Mesh *mesh;
- struct ParticleSystem *psys;
- struct Tex *noise_texture;
-
- /* initial velocity */
- /** Previous vertex positions in domain space. */
- float *verts_old;
- int numverts;
- float vel_multi; // Multiplier for inherited velocity
- float vel_normal;
- float vel_random;
- /* emission */
- float density;
- float color[3];
- float fuel_amount;
- /** Delta temperature (temp - ambient temp). */
- float temp;
- /** Density emitted within mesh volume. */
- float volume_density;
- /** Maximum emission distance from mesh surface. */
- float surface_distance;
- float particle_size;
- int subframes;
- /* texture control */
- float texture_size;
- float texture_offset;
- char _pad[4];
- /** MAX_CUSTOMDATA_LAYER_NAME. */
- char uvlayer_name[64];
- short vgroup_density;
-
- /** Smoke, flames, both, outflow. */
- short type;
- short source;
- short texture_type;
- /** Absolute emission et.c*/
- int flags;
-} SmokeFlowSettings;
-
-// struct BVHTreeFromMesh *bvh;
-// float mat[4][4];
-// float mat_old[4][4];
-
-/* collision objects (filled with smoke) */
-typedef struct SmokeCollSettings {
- /** For fast RNA access. */
- struct SmokeModifierData *smd;
- struct Mesh *mesh;
- float *verts_old;
- int numverts;
- short type; // static = 0, rigid = 1, dynamic = 2
- char _pad[2];
-} SmokeCollSettings;
-
-#endif
diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h
index 1c1bb9b9ce1..81548343da0 100644
--- a/source/blender/makesdna/DNA_sound_types.h
+++ b/source/blender/makesdna/DNA_sound_types.h
@@ -112,7 +112,7 @@ enum {
/* bSound->flags */
enum {
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
/* deprecated! used for sound actuator loading */
SOUND_FLAGS_3D = (1 << 3),
#endif
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 8261b9e678b..7adba2b7dbe 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1697,7 +1697,7 @@ typedef enum eSpace_Type {
SPACE_INFO = 7,
SPACE_SEQ = 8,
SPACE_TEXT = 9,
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
SPACE_IMASEL = 10, /* Deprecated */
SPACE_SOUND = 11, /* Deprecated */
#endif
@@ -1705,11 +1705,11 @@ typedef enum eSpace_Type {
SPACE_NLA = 13,
/* TODO: fully deprecate */
SPACE_SCRIPT = 14, /* Deprecated */
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
SPACE_TIME = 15, /* Deprecated */
#endif
SPACE_NODE = 16,
-#ifdef DNA_DEPRECATED
+#ifdef DNA_DEPRECATED_ALLOW
SPACE_LOGIC = 17, /* Deprecated */
#endif
SPACE_CONSOLE = 18,
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index fb23b39a616..1f92b134e4c 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -1012,10 +1012,10 @@ typedef enum eUserpref_UI_Flag {
USER_ZOOM_HORIZ = (1 << 26), /* for CONTINUE and DOLLY zoom */
USER_SPLASH_DISABLE = (1 << 27),
USER_HIDE_RECENT = (1 << 28),
-#ifdef DNA_DEPRECATED
- USER_SHOW_THUMBNAILS =
- (1 << 29), /* deprecated - We're just trying if there's much desire for this feature, or if
- we can make it go for good. Should be cleared if so - Julian, Oct. 2019 */
+#ifdef DNA_DEPRECATED_ALLOW
+ /* Deprecated: We're just trying if there's much desire for this feature,
+ * or if we can make it go for good. Should be cleared if so - Julian, Oct. 2019. */
+ USER_SHOW_THUMBNAILS = (1 << 29),
#endif
USER_SAVE_PROMPT = (1 << 30),
USER_HIDE_SYSTEM_BOOKMARKS = (1u << 31),
diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h
index 0bc35c15e35..404f483fde2 100644
--- a/source/blender/makesdna/intern/dna_rename_defs.h
+++ b/source/blender/makesdna/intern/dna_rename_defs.h
@@ -68,6 +68,13 @@ DNA_STRUCT_RENAME_ELEM(Camera, YF_dofdist, dof_distance)
DNA_STRUCT_RENAME_ELEM(Camera, clipend, clip_end)
DNA_STRUCT_RENAME_ELEM(Camera, clipsta, clip_start)
DNA_STRUCT_RENAME_ELEM(Collection, dupli_ofs, instance_offset)
+DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, cache_frame_pause_guiding, cache_frame_pause_guide)
+DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_alpha, guide_alpha)
+DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_beta, guide_beta)
+DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_parent, guide_parent)
+DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_source, guide_source)
+DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_vel_factor, guide_vel_factor)
+DNA_STRUCT_RENAME_ELEM(FluidEffectorSettings, guiding_mode, guide_mode)
DNA_STRUCT_RENAME_ELEM(Object, col, color)
DNA_STRUCT_RENAME_ELEM(Object, dup_group, instance_collection)
DNA_STRUCT_RENAME_ELEM(Object, dupfacesca, instance_faces_scale)
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index f4bc79b786a..dc32ca7e244 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -118,7 +118,7 @@ static const char *includefiles[] = {
"DNA_windowmanager_types.h",
"DNA_anim_types.h",
"DNA_boid_types.h",
- "DNA_smoke_types.h",
+ "DNA_fluid_types.h",
"DNA_speaker_types.h",
"DNA_movieclip_types.h",
"DNA_tracking_types.h",
@@ -903,7 +903,8 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
/* Write test to verify sizes are accurate. */
fprintf(file_verify, "/* Verify struct sizes and member offsets are as expected by DNA. */\n");
fprintf(file_verify, "#include \"BLI_assert.h\"\n\n");
- fprintf(file_verify, "#define DNA_DEPRECATED\n");
+ /* Needed so we can find offsets of deprecated structs. */
+ fprintf(file_verify, "#define DNA_DEPRECATED_ALLOW\n");
/* Workaround enum naming collision in static asserts
* (ideally this included a unique name/id per file). */
fprintf(file_verify, "#define assert_line_ assert_line_DNA_\n");
@@ -1579,7 +1580,7 @@ int main(int argc, char **argv)
#include "DNA_windowmanager_types.h"
#include "DNA_anim_types.h"
#include "DNA_boid_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_speaker_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_tracking_types.h"
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 00491f25b17..f8e78e9c8fc 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -35,12 +35,12 @@ struct ID;
struct IDOverrideLibrary;
struct IDOverrideLibraryProperty;
struct IDOverrideLibraryPropertyOperation;
+struct IDProperty;
struct ListBase;
struct Main;
struct ReportList;
struct Scene;
struct bContext;
-struct IDProperty;
/* Types */
extern BlenderRNA BLENDER_RNA;
@@ -263,7 +263,6 @@ extern StructRNA RNA_FloatProperty;
extern StructRNA RNA_FloorConstraint;
extern StructRNA RNA_FluidFluidSettings;
extern StructRNA RNA_FluidSettings;
-extern StructRNA RNA_FluidSimulationModifier;
extern StructRNA RNA_FollowPathConstraint;
extern StructRNA RNA_FreestyleLineSet;
extern StructRNA RNA_FreestyleLineStyle;
@@ -597,10 +596,10 @@ extern StructRNA RNA_ShrinkwrapModifier;
extern StructRNA RNA_SimpleDeformModifier;
extern StructRNA RNA_SimplifyGpencilModifier;
extern StructRNA RNA_SkinModifier;
-extern StructRNA RNA_SmokeCollSettings;
-extern StructRNA RNA_SmokeDomainSettings;
-extern StructRNA RNA_SmokeFlowSettings;
-extern StructRNA RNA_SmokeModifier;
+extern StructRNA RNA_FluidEffectorSettings;
+extern StructRNA RNA_FluidDomainSettings;
+extern StructRNA RNA_FluidFlowSettings;
+extern StructRNA RNA_FluidModifier;
extern StructRNA RNA_SmoothGpencilModifier;
extern StructRNA RNA_SmoothModifier;
extern StructRNA RNA_SoftBodyModifier;
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index f3ade54d5ec..3082daa83a4 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -44,7 +44,7 @@ set(DEFSRC
rna_depsgraph.c
rna_dynamicpaint.c
rna_fcurve.c
- rna_fluidsim.c
+ rna_fluid.c
rna_gpencil.c
rna_gpencil_modifier.c
rna_image.c
@@ -77,7 +77,6 @@ set(DEFSRC
rna_sculpt_paint.c
rna_sequencer.c
rna_shader_fx.c
- rna_smoke.c
rna_sound.c
rna_space.c
rna_speaker.c
@@ -241,16 +240,12 @@ if(WITH_CODEC_FFMPEG)
add_definitions(-DWITH_FFMPEG)
endif()
-if(WITH_MOD_FLUID)
- add_definitions(-DWITH_MOD_FLUID)
-endif()
-
if(WITH_FFTW3)
add_definitions(-DWITH_FFTW3)
endif()
-if(WITH_MOD_SMOKE)
- add_definitions(-DWITH_SMOKE)
+if(WITH_MOD_FLUID)
+ add_definitions(-DWITH_FLUID)
endif()
if(WITH_MOD_OCEANSIM)
@@ -348,7 +343,7 @@ blender_include_dirs(
../../../../intern/glew-mx
../../../../intern/guardedalloc
../../../../intern/memutil
- ../../../../intern/smoke/extern
+ ../../../../intern/mantaflow/extern
)
blender_include_dirs_sys(
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index bef2e34065f..e5da9ee4ecd 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -4231,7 +4231,6 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_curve.c", "rna_curve_api.c", RNA_def_curve},
{"rna_dynamicpaint.c", NULL, RNA_def_dynamic_paint},
{"rna_fcurve.c", "rna_fcurve_api.c", RNA_def_fcurve},
- {"rna_fluidsim.c", NULL, RNA_def_fluidsim},
{"rna_gpencil.c", NULL, RNA_def_gpencil},
{"rna_image.c", "rna_image_api.c", RNA_def_image},
{"rna_key.c", NULL, RNA_def_key},
@@ -4240,6 +4239,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_layer.c", NULL, RNA_def_view_layer},
{"rna_linestyle.c", NULL, RNA_def_linestyle},
{"rna_main.c", "rna_main_api.c", RNA_def_main},
+ {"rna_fluid.c", NULL, RNA_def_fluid},
{"rna_material.c", "rna_material_api.c", RNA_def_material},
{"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh},
{"rna_meta.c", "rna_meta_api.c", RNA_def_meta},
@@ -4263,7 +4263,6 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_screen.c", NULL, RNA_def_screen},
{"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint},
{"rna_sequencer.c", "rna_sequencer_api.c", RNA_def_sequencer},
- {"rna_smoke.c", NULL, RNA_def_smoke},
{"rna_space.c", "rna_space_api.c", RNA_def_space},
{"rna_speaker.c", NULL, RNA_def_speaker},
{"rna_test.c", NULL, RNA_def_test},
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 2d70950ce7b..5b683ffd80e 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1596,6 +1596,22 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem brush_jitter_unit_items[] = {
+ {BRUSH_ABSOLUTE_JITTER, "VIEW", 0, "View", "Jitterring happens in screen space, in pixels"},
+ {0, "BRUSH", 0, "Brush", "Jitterring happens relative to the brush size"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem falloff_shape_unit_items[] = {
+ {0, "SPHERE", 0, "Sphere", "Apply brush influence in a Sphere, outwards from the center"},
+ {PAINT_FALLOFF_SHAPE_TUBE,
+ "PROJECTED",
+ 0,
+ "Projected",
+ "Apply brush influence in a 2D circle, projected from the view"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem brush_curve_preset_items[] = {
{BRUSH_CURVE_CUSTOM, "CUSTOM", ICON_RNDCURVE, "Custom", ""},
{BRUSH_CURVE_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
@@ -1704,6 +1720,19 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "jitter_unit", PROP_ENUM, PROP_NONE); /* as an enum */
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+ RNA_def_property_enum_items(prop, brush_jitter_unit_items);
+ RNA_def_property_ui_text(
+ prop, "Jitter Unit", "Jitter in screen space or relative to brush size");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "falloff_shape", PROP_ENUM, PROP_NONE); /* as an enum */
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "falloff_shape");
+ RNA_def_property_enum_items(prop, falloff_shape_unit_items);
+ RNA_def_property_ui_text(prop, "Falloff Shape", "Use projected or spherical falloff");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
/* number values */
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
RNA_def_property_int_funcs(prop, NULL, "rna_Brush_set_size", NULL);
@@ -1993,13 +2022,6 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* flag */
- /* This is an enum but its unlikely we add other shapes, so expose as a boolean. */
- prop = RNA_def_property(srna, "use_projected", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "falloff_shape", PAINT_FALLOFF_SHAPE_TUBE);
- RNA_def_property_ui_text(
- prop, "2D Falloff", "Apply brush influence in 2D circle instead of a sphere");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
prop = RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH);
RNA_def_property_ui_text(
@@ -2045,7 +2067,7 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_paint_antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "sampling_flag", BRUSH_PAINT_ANTIALIASING);
- RNA_def_property_ui_text(prop, "Antialasing", "Smooths the edges of the strokes");
+ RNA_def_property_ui_text(prop, "Anti-Aliasing", "Smooths the edges of the strokes");
prop = RNA_def_property(srna, "use_multiplane_scrape_dynamic", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_MULTIPLANE_SCRAPE_DYNAMIC);
@@ -2117,13 +2139,6 @@ static void rna_def_brush(BlenderRNA *brna)
prop, "Inverse Smooth Pressure", "Lighter pressure causes more smoothing to be applied");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "use_relative_jitter", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_ABSOLUTE_JITTER);
- RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true);
- RNA_def_property_ui_text(
- prop, "Absolute Jitter", "Jittering happens in screen space, not relative to brush size");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
-
prop = RNA_def_property(srna, "use_plane_trim", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_PLANE_TRIM);
RNA_def_property_ui_text(prop, "Use Plane Trim", "Enable Plane Trim");
diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c
new file mode 100644
index 00000000000..44bcab7d41a
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_fluid.c
@@ -0,0 +1,2590 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup RNA
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+#include "BLI_sys_types.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "BKE_modifier.h"
+#include "BKE_fluid.h"
+#include "BKE_pointcache.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_object_force_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_fluid_types.h"
+#include "DNA_particle_types.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#ifdef RNA_RUNTIME
+
+# include "BLI_math.h"
+# include "BLI_threads.h"
+
+# include "BKE_colorband.h"
+# include "BKE_context.h"
+# include "BKE_particle.h"
+
+# include "DEG_depsgraph.h"
+# include "DEG_depsgraph_build.h"
+
+# include "manta_fluid_API.h"
+
+static void rna_Fluid_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+
+ // Needed for liquid domain objects
+ Object *ob = (Object *)ptr->owner_id;
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+}
+
+static void rna_Fluid_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ rna_Fluid_update(bmain, scene, ptr);
+ DEG_relations_tag_update(bmain);
+}
+
+static void rna_Fluid_resetCache(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ if (settings->mmd && settings->mmd->domain) {
+ settings->mmd->domain->cache_flag |= (FLUID_DOMAIN_OUTDATED_DATA |
+ FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH |
+ FLUID_DOMAIN_OUTDATED_PARTICLES);
+ scene->r.cfra = settings->cache_frame_start;
+ }
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+}
+static void rna_Fluid_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+
+# ifdef WITH_FLUID
+ {
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ BKE_fluid_modifier_reset(settings->mmd);
+ }
+# endif
+
+ rna_Fluid_resetCache(bmain, scene, ptr);
+
+ rna_Fluid_update(bmain, scene, ptr);
+}
+
+static void rna_Fluid_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+# ifdef WITH_FLUID
+ BKE_fluid_modifier_reset(settings->mmd);
+# endif
+
+ if (settings->mmd && settings->mmd->domain) {
+ settings->mmd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED;
+ }
+
+ rna_Fluid_dependency_update(bmain, scene, ptr);
+}
+
+static void rna_Fluid_parts_create(Main *bmain,
+ PointerRNA *ptr,
+ const char *pset_name,
+ const char *parts_name,
+ const char *psys_name,
+ int psys_type)
+{
+# ifndef WITH_FLUID
+ UNUSED_VARS(bmain, ptr, pset_name, parts_name, psys_name, psys_type);
+# else
+ Object *ob = (Object *)ptr->owner_id;
+ BKE_fluid_particle_system_create(bmain, ob, pset_name, parts_name, psys_name, psys_type);
+# endif
+}
+
+static void rna_Fluid_parts_delete(PointerRNA *ptr, int ptype)
+{
+# ifndef WITH_FLUID
+ UNUSED_VARS(ptr, ptype);
+# else
+ Object *ob = (Object *)ptr->owner_id;
+ BKE_fluid_particle_system_destroy(ob, ptype);
+# endif
+}
+
+static bool rna_Fluid_parts_exists(PointerRNA *ptr, int ptype)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ ParticleSystem *psys;
+
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ if (psys->part->type == ptype) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void rna_Fluid_draw_type_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ struct PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+ /* Wireframe mode more convenient when particles present */
+ if (settings->particle_type == 0) {
+ ob->dt = OB_SOLID;
+ }
+ else {
+ ob->dt = OB_WIRE;
+ }
+}
+
+static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ FluidModifierData *mmd;
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FLIP);
+
+ if (ob->type == OB_MESH && !exists) {
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "FlipParticleSettings",
+ "FLIP Particles",
+ "FLIP Particle System",
+ PART_FLUID_FLIP);
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_FLIP;
+ }
+ else {
+ rna_Fluid_parts_delete(ptr, PART_FLUID_FLIP);
+ rna_Fluid_resetCache(bmain, scene, ptr);
+
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP;
+ }
+ rna_Fluid_draw_type_update(NULL, NULL, ptr);
+ rna_Fluid_reset(bmain, scene, ptr);
+}
+
+static void rna_Fluid_spray_parts_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ FluidModifierData *mmd;
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_SPRAY);
+
+ if (ob->type == OB_MESH && !exists) {
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "SprayParticleSettings",
+ "Spray Particles",
+ "Spray Particle System",
+ PART_FLUID_SPRAY);
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_SPRAY;
+ }
+ else {
+ rna_Fluid_parts_delete(ptr, PART_FLUID_SPRAY);
+ rna_Fluid_resetCache(bmain, scene, ptr);
+
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_SPRAY;
+ }
+ rna_Fluid_draw_type_update(NULL, NULL, ptr);
+ rna_Fluid_reset(bmain, scene, ptr);
+}
+
+static void rna_Fluid_bubble_parts_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ FluidModifierData *mmd;
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_BUBBLE);
+
+ if (ob->type == OB_MESH && !exists) {
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "BubbleParticleSettings",
+ "Bubble Particles",
+ "Bubble Particle System",
+ PART_FLUID_BUBBLE);
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_BUBBLE;
+ }
+ else {
+ rna_Fluid_parts_delete(ptr, PART_FLUID_BUBBLE);
+ rna_Fluid_resetCache(bmain, scene, ptr);
+
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_BUBBLE;
+ }
+ rna_Fluid_draw_type_update(NULL, NULL, ptr);
+ rna_Fluid_reset(bmain, scene, ptr);
+}
+
+static void rna_Fluid_foam_parts_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ FluidModifierData *mmd;
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FOAM);
+
+ if (ob->type == OB_MESH && !exists) {
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "FoamParticleSettings",
+ "Foam Particles",
+ "Foam Particle System",
+ PART_FLUID_FOAM);
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_FOAM;
+ }
+ else {
+ rna_Fluid_parts_delete(ptr, PART_FLUID_FOAM);
+ rna_Fluid_resetCache(bmain, scene, ptr);
+
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FOAM;
+ }
+ rna_Fluid_draw_type_update(NULL, NULL, ptr);
+ rna_Fluid_reset(bmain, scene, ptr);
+}
+
+static void rna_Fluid_tracer_parts_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ FluidModifierData *mmd;
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+ bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_TRACER);
+
+ if (ob->type == OB_MESH && !exists) {
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "TracerParticleSettings",
+ "Tracer Particles",
+ "Tracer Particle System",
+ PART_FLUID_TRACER);
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_TRACER;
+ }
+ else {
+ rna_Fluid_parts_delete(ptr, PART_FLUID_TRACER);
+ rna_Fluid_resetCache(bmain, scene, ptr);
+
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_TRACER;
+ }
+ rna_Fluid_draw_type_update(NULL, NULL, ptr);
+ rna_Fluid_reset(bmain, scene, ptr);
+}
+
+static void rna_Fluid_combined_export_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ FluidModifierData *mmd;
+ mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
+
+ if (mmd->domain->sndparticle_combined_export == SNDPARTICLE_COMBINED_EXPORT_OFF) {
+ rna_Fluid_parts_delete(ptr, (PART_FLUID_SPRAY | PART_FLUID_FOAM | PART_FLUID_BUBBLE));
+
+ // re-add each particle type if enabled
+ if ((mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) != 0) {
+ rna_Fluid_spray_parts_update(bmain, scene, ptr);
+ }
+ if ((mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) != 0) {
+ rna_Fluid_foam_parts_update(bmain, scene, ptr);
+ }
+ if ((mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) != 0) {
+ rna_Fluid_bubble_parts_update(bmain, scene, ptr);
+ }
+ }
+ else if (mmd->domain->sndparticle_combined_export == SNDPARTICLE_COMBINED_EXPORT_SPRAY_FOAM) {
+ if (ob->type == OB_MESH &&
+ !rna_Fluid_parts_exists(ptr, (PART_FLUID_SPRAY | PART_FLUID_FOAM))) {
+ rna_Fluid_parts_delete(ptr, (PART_FLUID_SPRAY | PART_FLUID_FOAM));
+ }
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "SprayFoamParticleSettings",
+ "Spray + Foam Particles",
+ "Spray + Foam Particle System",
+ (PART_FLUID_SPRAY | PART_FLUID_FOAM));
+
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_SPRAY;
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_FOAM;
+
+ // re-add bubbles if enabled
+ if ((mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) != 0) {
+ rna_Fluid_bubble_parts_update(bmain, scene, ptr);
+ }
+ }
+ else if (mmd->domain->sndparticle_combined_export == SNDPARTICLE_COMBINED_EXPORT_SPRAY_BUBBLE) {
+ if (ob->type == OB_MESH &&
+ !rna_Fluid_parts_exists(ptr, (PART_FLUID_SPRAY | PART_FLUID_BUBBLE))) {
+ rna_Fluid_parts_delete(ptr, (PART_FLUID_SPRAY | PART_FLUID_BUBBLE));
+ }
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "SprayBubbleParticleSettings",
+ "Spray + Bubble Particles",
+ "Spray + Bubble Particle System",
+ (PART_FLUID_SPRAY | PART_FLUID_BUBBLE));
+
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_SPRAY;
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_BUBBLE;
+
+ // re-add foam if enabled
+ if ((mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) != 0) {
+ rna_Fluid_foam_parts_update(bmain, scene, ptr);
+ }
+ }
+ else if (mmd->domain->sndparticle_combined_export == SNDPARTICLE_COMBINED_EXPORT_FOAM_BUBBLE) {
+ if (ob->type == OB_MESH &&
+ !rna_Fluid_parts_exists(ptr, (PART_FLUID_FOAM | PART_FLUID_BUBBLE))) {
+ rna_Fluid_parts_delete(ptr, (PART_FLUID_FOAM | PART_FLUID_BUBBLE));
+ }
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "FoamBubbleParticleSettings",
+ "Foam + Bubble Particles",
+ "Foam + Bubble Particle System",
+ (PART_FLUID_FOAM | PART_FLUID_BUBBLE));
+
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_FOAM;
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_BUBBLE;
+
+ // re-add spray if enabled
+ if ((mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) != 0) {
+ rna_Fluid_spray_parts_update(bmain, scene, ptr);
+ }
+ }
+ else if (mmd->domain->sndparticle_combined_export ==
+ SNDPARTICLE_COMBINED_EXPORT_SPRAY_FOAM_BUBBLE) {
+ if (ob->type == OB_MESH &&
+ !rna_Fluid_parts_exists(ptr, (PART_FLUID_SPRAY | PART_FLUID_FOAM | PART_FLUID_BUBBLE))) {
+ rna_Fluid_parts_delete(ptr, (PART_FLUID_SPRAY | PART_FLUID_FOAM | PART_FLUID_BUBBLE));
+ }
+ rna_Fluid_parts_create(bmain,
+ ptr,
+ "SprayFoamBubbleParticleSettings",
+ "Spray + Foam + Bubble Particles",
+ "Spray + Foam + Bubble Particle System",
+ (PART_FLUID_SPRAY | PART_FLUID_FOAM | PART_FLUID_BUBBLE));
+
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_SPRAY;
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_FOAM;
+ mmd->domain->particle_type |= FLUID_DOMAIN_PARTICLE_BUBBLE;
+ }
+ else {
+ // sanity check, should not occur
+ printf("ERROR: Unexpected combined export setting encountered!");
+ }
+ rna_Fluid_resetCache(bmain, scene, ptr);
+ rna_Fluid_draw_type_update(NULL, NULL, ptr);
+}
+
+static void rna_Fluid_cachetype_mesh_set(struct PointerRNA *ptr, int value)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+ if (value != settings->cache_mesh_format) {
+ /* TODO (sebbas): Clear old caches. */
+ settings->cache_mesh_format = value;
+ }
+}
+
+static void rna_Fluid_cachetype_data_set(struct PointerRNA *ptr, int value)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+ if (value != settings->cache_data_format) {
+ /* TODO (sebbas): Clear old caches. */
+ settings->cache_data_format = value;
+ }
+}
+
+static void rna_Fluid_cachetype_particle_set(struct PointerRNA *ptr, int value)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+ if (value != settings->cache_particle_format) {
+ /* TODO (sebbas): Clear old caches. */
+ settings->cache_particle_format = value;
+ }
+}
+
+static void rna_Fluid_cachetype_noise_set(struct PointerRNA *ptr, int value)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+ if (value != settings->cache_noise_format) {
+ /* TODO (sebbas): Clear old caches. */
+ settings->cache_noise_format = value;
+ }
+}
+
+static void rna_Fluid_cachetype_set(struct PointerRNA *ptr, int value)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+ if (value != settings->cache_type) {
+ settings->cache_type = value;
+ settings->cache_flag = 0;
+ }
+}
+
+static void rna_Fluid_guide_parent_set(struct PointerRNA *ptr,
+ struct PointerRNA value,
+ struct ReportList *UNUSED(reports))
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ Object *par = (Object *)value.data;
+
+ FluidModifierData *mmd_par = NULL;
+
+ if (par != NULL) {
+ mmd_par = (FluidModifierData *)modifiers_findByType(par, eModifierType_Fluid);
+ if (mmd_par && mmd_par->domain) {
+ mds->guide_parent = value.data;
+ copy_v3_v3_int(mds->guide_res, mmd_par->domain->res);
+ }
+ }
+ else {
+ mds->guide_parent = NULL;
+ }
+}
+
+static const EnumPropertyItem *rna_Fluid_cachetype_mesh_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem = 0;
+
+ tmp.value = FLUID_DOMAIN_FILE_BIN_OBJECT;
+ tmp.identifier = "BOBJECT";
+ tmp.name = "Binary Object files";
+ tmp.description = "Binary object file format";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ tmp.value = FLUID_DOMAIN_FILE_OBJECT;
+ tmp.identifier = "OBJECT";
+ tmp.name = "Object files";
+ tmp.description = "Object file format";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static const EnumPropertyItem *rna_Fluid_cachetype_volume_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem = 0;
+
+ tmp.value = FLUID_DOMAIN_FILE_UNI;
+ tmp.identifier = "UNI";
+ tmp.name = "Uni Cache";
+ tmp.description = "Uni file format";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+# ifdef WITH_OPENVDB
+ tmp.value = FLUID_DOMAIN_FILE_OPENVDB;
+ tmp.identifier = "OPENVDB";
+ tmp.name = "OpenVDB";
+ tmp.description = "OpenVDB file format";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+# endif
+
+ tmp.value = FLUID_DOMAIN_FILE_RAW;
+ tmp.identifier = "RAW";
+ tmp.name = "Raw Cache";
+ tmp.description = "Raw file format";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static const EnumPropertyItem *rna_Fluid_cachetype_particle_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem = 0;
+
+ tmp.value = FLUID_DOMAIN_FILE_UNI;
+ tmp.identifier = "UNI";
+ tmp.name = "Uni Cache";
+ tmp.description = "Uni file format";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static void rna_Fluid_collisionextents_set(struct PointerRNA *ptr, int value, bool clear)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ if (clear) {
+ settings->border_collisions &= value;
+ }
+ else {
+ settings->border_collisions |= value;
+ }
+}
+
+static void rna_Fluid_cache_directory_set(struct PointerRNA *ptr, const char *value)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+
+ if (STREQ(settings->cache_directory, value)) {
+ return;
+ }
+
+ BLI_strncpy(settings->cache_directory, value, sizeof(settings->cache_directory));
+
+ /* TODO (sebbas): Read cache state in order to set cache bake flags and cache pause frames
+ * correctly */
+ // settings->cache_flag = 0;
+}
+
+static void rna_Fluid_domaintype_set(struct PointerRNA *ptr, int value)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ Object *ob = (Object *)ptr->owner_id;
+
+ if (value != settings->type) {
+ /* Set common values for liquid/smoke domain: cache type,
+ * border collision and viewport draw-type. */
+ if (value == FLUID_DOMAIN_TYPE_GAS) {
+ rna_Fluid_cachetype_mesh_set(ptr, FLUID_DOMAIN_FILE_BIN_OBJECT);
+ rna_Fluid_cachetype_data_set(ptr, FLUID_DOMAIN_FILE_UNI);
+ rna_Fluid_cachetype_particle_set(ptr, FLUID_DOMAIN_FILE_UNI);
+ rna_Fluid_cachetype_noise_set(ptr, FLUID_DOMAIN_FILE_UNI);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_FRONT, 1);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_BACK, 1);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_RIGHT, 1);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_LEFT, 1);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_TOP, 1);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_BOTTOM, 1);
+ ob->dt = OB_WIRE;
+ }
+ else if (value == FLUID_DOMAIN_TYPE_LIQUID) {
+ rna_Fluid_cachetype_mesh_set(ptr, FLUID_DOMAIN_FILE_BIN_OBJECT);
+ rna_Fluid_cachetype_data_set(ptr, FLUID_DOMAIN_FILE_UNI);
+ rna_Fluid_cachetype_particle_set(ptr, FLUID_DOMAIN_FILE_UNI);
+ rna_Fluid_cachetype_noise_set(ptr, FLUID_DOMAIN_FILE_UNI);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_FRONT, 0);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_BACK, 0);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_RIGHT, 0);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_LEFT, 0);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_TOP, 0);
+ rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_BOTTOM, 0);
+ ob->dt = OB_SOLID;
+ }
+
+ /* Set actual domain type */
+ settings->type = value;
+ }
+}
+
+static char *rna_FluidDomainSettings_path(PointerRNA *ptr)
+{
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ ModifierData *md = (ModifierData *)settings->mmd;
+ char name_esc[sizeof(md->name) * 2];
+
+ BLI_strescape(name_esc, md->name, sizeof(name_esc));
+ return BLI_sprintfN("modifiers[\"%s\"].domain_settings", name_esc);
+}
+
+static char *rna_FluidFlowSettings_path(PointerRNA *ptr)
+{
+ FluidFlowSettings *settings = (FluidFlowSettings *)ptr->data;
+ ModifierData *md = (ModifierData *)settings->mmd;
+ char name_esc[sizeof(md->name) * 2];
+
+ BLI_strescape(name_esc, md->name, sizeof(name_esc));
+ return BLI_sprintfN("modifiers[\"%s\"].flow_settings", name_esc);
+}
+
+static char *rna_FluidEffectorSettings_path(PointerRNA *ptr)
+{
+ FluidEffectorSettings *settings = (FluidEffectorSettings *)ptr->data;
+ ModifierData *md = (ModifierData *)settings->mmd;
+ char name_esc[sizeof(md->name) * 2];
+
+ BLI_strescape(name_esc, md->name, sizeof(name_esc));
+ return BLI_sprintfN("modifiers[\"%s\"].effector_settings", name_esc);
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Grid Accessors
+ * \{ */
+
+# ifdef WITH_FLUID
+
+static int rna_FluidModifier_grid_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ float *density = NULL;
+ int size = 0;
+
+ if (mds->flags & FLUID_DOMAIN_USE_NOISE && mds->fluid) {
+ /* high resolution smoke */
+ int res[3];
+
+ manta_smoke_turbulence_get_res(mds->fluid, res);
+ size = res[0] * res[1] * res[2];
+
+ density = manta_smoke_turbulence_get_density(mds->fluid);
+ }
+ else if (mds->fluid) {
+ /* regular resolution */
+ size = mds->res[0] * mds->res[1] * mds->res[2];
+ density = manta_smoke_get_density(mds->fluid);
+ }
+
+ length[0] = (density) ? size : 0;
+ return length[0];
+}
+
+static int rna_FluidModifier_color_grid_get_length(PointerRNA *ptr,
+ int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ rna_FluidModifier_grid_get_length(ptr, length);
+
+ length[0] *= 4;
+ return length[0];
+}
+
+static int rna_FluidModifier_velocity_grid_get_length(PointerRNA *ptr,
+ int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ float *vx = NULL;
+ float *vy = NULL;
+ float *vz = NULL;
+ int size = 0;
+
+ /* Velocity data is always low-resolution. */
+ if (mds->fluid) {
+ size = 3 * mds->res[0] * mds->res[1] * mds->res[2];
+ vx = manta_get_velocity_x(mds->fluid);
+ vy = manta_get_velocity_y(mds->fluid);
+ vz = manta_get_velocity_z(mds->fluid);
+ }
+
+ length[0] = (vx && vy && vz) ? size : 0;
+ return length[0];
+}
+
+static int rna_FluidModifier_heat_grid_get_length(PointerRNA *ptr,
+ int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ float *heat = NULL;
+ int size = 0;
+
+ /* Heat data is always low-resolution. */
+ if (mds->fluid) {
+ size = mds->res[0] * mds->res[1] * mds->res[2];
+ heat = manta_smoke_get_heat(mds->fluid);
+ }
+
+ length[0] = (heat) ? size : 0;
+ return length[0];
+}
+
+static void rna_FluidModifier_density_grid_get(PointerRNA *ptr, float *values)
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_FluidModifier_grid_get_length(ptr, length);
+ float *density;
+
+ BLI_rw_mutex_lock(mds->fluid_mutex, THREAD_LOCK_READ);
+
+ if (mds->flags & FLUID_DOMAIN_USE_NOISE && mds->fluid) {
+ density = manta_smoke_turbulence_get_density(mds->fluid);
+ }
+ else {
+ density = manta_smoke_get_density(mds->fluid);
+ }
+
+ memcpy(values, density, size * sizeof(float));
+
+ BLI_rw_mutex_unlock(mds->fluid_mutex);
+}
+
+static void rna_FluidModifier_velocity_grid_get(PointerRNA *ptr, float *values)
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_FluidModifier_velocity_grid_get_length(ptr, length);
+ float *vx, *vy, *vz;
+ int i;
+
+ BLI_rw_mutex_lock(mds->fluid_mutex, THREAD_LOCK_READ);
+
+ vx = manta_get_velocity_x(mds->fluid);
+ vy = manta_get_velocity_y(mds->fluid);
+ vz = manta_get_velocity_z(mds->fluid);
+
+ for (i = 0; i < size; i += 3) {
+ *(values++) = *(vx++);
+ *(values++) = *(vy++);
+ *(values++) = *(vz++);
+ }
+
+ BLI_rw_mutex_unlock(mds->fluid_mutex);
+}
+
+static void rna_FluidModifier_color_grid_get(PointerRNA *ptr, float *values)
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_FluidModifier_grid_get_length(ptr, length);
+
+ BLI_rw_mutex_lock(mds->fluid_mutex, THREAD_LOCK_READ);
+
+ if (!mds->fluid) {
+ memset(values, 0, size * sizeof(float));
+ }
+ else {
+ if (mds->flags & FLUID_DOMAIN_USE_NOISE) {
+ if (manta_smoke_turbulence_has_colors(mds->fluid)) {
+ manta_smoke_turbulence_get_rgba(mds->fluid, values, 0);
+ }
+ else {
+ manta_smoke_turbulence_get_rgba_from_density(mds->fluid, mds->active_color, values, 0);
+ }
+ }
+ else {
+ if (manta_smoke_has_colors(mds->fluid)) {
+ manta_smoke_get_rgba(mds->fluid, values, 0);
+ }
+ else {
+ manta_smoke_get_rgba_from_density(mds->fluid, mds->active_color, values, 0);
+ }
+ }
+ }
+
+ BLI_rw_mutex_unlock(mds->fluid_mutex);
+}
+
+static void rna_FluidModifier_flame_grid_get(PointerRNA *ptr, float *values)
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_FluidModifier_grid_get_length(ptr, length);
+ float *flame;
+
+ BLI_rw_mutex_lock(mds->fluid_mutex, THREAD_LOCK_READ);
+
+ if (mds->flags & FLUID_DOMAIN_USE_NOISE && mds->fluid) {
+ flame = manta_smoke_turbulence_get_flame(mds->fluid);
+ }
+ else {
+ flame = manta_smoke_get_flame(mds->fluid);
+ }
+
+ if (flame) {
+ memcpy(values, flame, size * sizeof(float));
+ }
+ else {
+ memset(values, 0, size * sizeof(float));
+ }
+
+ BLI_rw_mutex_unlock(mds->fluid_mutex);
+}
+
+static void rna_FluidModifier_heat_grid_get(PointerRNA *ptr, float *values)
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_FluidModifier_heat_grid_get_length(ptr, length);
+ float *heat;
+
+ BLI_rw_mutex_lock(mds->fluid_mutex, THREAD_LOCK_READ);
+
+ heat = manta_smoke_get_heat(mds->fluid);
+
+ if (heat != NULL) {
+ /* scale heat values from -2.0-2.0 to -1.0-1.0. */
+ for (int i = 0; i < size; i++) {
+ values[i] = heat[i] * 0.5f;
+ }
+ }
+ else {
+ memset(values, 0, size * sizeof(float));
+ }
+
+ BLI_rw_mutex_unlock(mds->fluid_mutex);
+}
+
+static void rna_FluidModifier_temperature_grid_get(PointerRNA *ptr, float *values)
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_FluidModifier_grid_get_length(ptr, length);
+ float *flame;
+
+ BLI_rw_mutex_lock(mds->fluid_mutex, THREAD_LOCK_READ);
+
+ if (mds->flags & FLUID_DOMAIN_USE_NOISE && mds->fluid) {
+ flame = manta_smoke_turbulence_get_flame(mds->fluid);
+ }
+ else {
+ flame = manta_smoke_get_flame(mds->fluid);
+ }
+
+ if (flame) {
+ /* Output is such that 0..1 maps to 0..1000K */
+ float offset = mds->flame_ignition;
+ float scale = mds->flame_max_temp - mds->flame_ignition;
+
+ for (int i = 0; i < size; i++) {
+ values[i] = (flame[i] > 0.01f) ? offset + flame[i] * scale : 0.0f;
+ }
+ }
+ else {
+ memset(values, 0, size * sizeof(float));
+ }
+
+ BLI_rw_mutex_unlock(mds->fluid_mutex);
+}
+# endif /* WITH_FLUID */
+
+/** \} */
+
+static void rna_FluidFlow_density_vgroup_get(PointerRNA *ptr, char *value)
+{
+ FluidFlowSettings *flow = (FluidFlowSettings *)ptr->data;
+ rna_object_vgroup_name_index_get(ptr, value, flow->vgroup_density);
+}
+
+static int rna_FluidFlow_density_vgroup_length(PointerRNA *ptr)
+{
+ FluidFlowSettings *flow = (FluidFlowSettings *)ptr->data;
+ return rna_object_vgroup_name_index_length(ptr, flow->vgroup_density);
+}
+
+static void rna_FluidFlow_density_vgroup_set(struct PointerRNA *ptr, const char *value)
+{
+ FluidFlowSettings *flow = (FluidFlowSettings *)ptr->data;
+ rna_object_vgroup_name_index_set(ptr, value, &flow->vgroup_density);
+}
+
+static void rna_FluidFlow_uvlayer_set(struct PointerRNA *ptr, const char *value)
+{
+ FluidFlowSettings *flow = (FluidFlowSettings *)ptr->data;
+ rna_object_uvlayer_name_set(ptr, value, flow->uvlayer_name, sizeof(flow->uvlayer_name));
+}
+
+static void rna_Fluid_use_color_ramp_set(struct PointerRNA *ptr, bool value)
+{
+ FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data;
+
+ mds->use_coba = value;
+
+ if (value && mds->coba == NULL) {
+ mds->coba = BKE_colorband_add(false);
+ }
+}
+
+static void rna_Fluid_flowsource_set(struct PointerRNA *ptr, int value)
+{
+ FluidFlowSettings *settings = (FluidFlowSettings *)ptr->data;
+
+ if (value != settings->source) {
+ settings->source = value;
+ }
+}
+
+static const EnumPropertyItem *rna_Fluid_flowsource_itemf(bContext *UNUSED(C),
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ FluidFlowSettings *settings = (FluidFlowSettings *)ptr->data;
+
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem = 0;
+
+ tmp.value = FLUID_FLOW_SOURCE_MESH;
+ tmp.identifier = "MESH";
+ tmp.icon = ICON_META_CUBE;
+ tmp.name = "Mesh";
+ tmp.description = "Emit fluid from mesh surface or volume";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ if (settings->type != FLUID_FLOW_TYPE_LIQUID) {
+ tmp.value = FLUID_FLOW_SOURCE_PARTICLES;
+ tmp.identifier = "PARTICLES";
+ tmp.icon = ICON_PARTICLES;
+ tmp.name = "Particle System";
+ tmp.description = "Emit smoke from particles";
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+static void rna_Fluid_flowtype_set(struct PointerRNA *ptr, int value)
+{
+ FluidFlowSettings *settings = (FluidFlowSettings *)ptr->data;
+
+ if (value != settings->type) {
+ settings->type = value;
+
+ /* Force flow source to mesh */
+ if (value == FLUID_FLOW_TYPE_LIQUID) {
+ rna_Fluid_flowsource_set(ptr, FLUID_FLOW_SOURCE_MESH);
+ settings->surface_distance = 0.0f;
+ }
+ else {
+ settings->surface_distance = 1.5f;
+ }
+ }
+}
+
+#else
+
+static void rna_def_fluid_mesh_vertices(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "FluidDomainVertexVelocity", NULL);
+ RNA_def_struct_ui_text(srna, "Fluid Mesh Velocity", "Velocity of a simulated fluid mesh");
+ RNA_def_struct_ui_icon(srna, ICON_VERTEXSEL);
+
+ prop = RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VELOCITY);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_float_sdna(prop, NULL, "vel");
+ RNA_def_property_ui_text(prop, "Velocity", "");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+}
+
+static void rna_def_fluid_domain_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem domain_types[] = {
+ {FLUID_DOMAIN_TYPE_GAS, "GAS", 0, "Gas", "Create domain for gases"},
+ {FLUID_DOMAIN_TYPE_LIQUID, "LIQUID", 0, "Liquid", "Create domain for liquids"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static const EnumPropertyItem prop_noise_type_items[] = {
+ {FLUID_NOISE_TYPE_WAVELET, "NOISEWAVE", 0, "Wavelet", ""},
+ {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
+ {VDB_COMPRESSION_BLOSC,
+ "BLOSC",
+ 0,
+ "Blosc",
+ "Multithreaded compression, similar in size and quality as 'Zip'"},
+# endif
+ {VDB_COMPRESSION_NONE, "NONE", 0, "None", "Do not use any compression"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static const EnumPropertyItem cache_comp_items[] = {
+ {SM_CACHE_LIGHT, "CACHELIGHT", 0, "Lite", "Fast but not so effective compression"},
+ {SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem smoke_highres_sampling_items[] = {
+ {SM_HRES_FULLSAMPLE, "FULLSAMPLE", 0, "Full Sample", ""},
+ {SM_HRES_LINEAR, "LINEAR", 0, "Linear", ""},
+ {SM_HRES_NEAREST, "NEAREST", 0, "Nearest", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static EnumPropertyItem cache_types[] = {
+ {FLUID_DOMAIN_CACHE_REPLAY,
+ "REPLAY",
+ 0,
+ "Replay",
+ "Use the timeline to bake the scene. Pausing and resuming possible."},
+ {FLUID_DOMAIN_CACHE_MODULAR,
+ "MODULAR",
+ 0,
+ "Modular",
+ "Bake every stage of the simulation on its own. Can pause and resume bake jobs."},
+ {FLUID_DOMAIN_CACHE_FINAL, "FINAL", 0, "Final", "Bake the entire simulation at once."},
+ {0, NULL, 0, NULL, NULL}};
+
+ static const EnumPropertyItem smoke_data_depth_items[] = {
+ {16, "16", 0, "Float (Half)", "Half float (16 bit data)"},
+ {0, "32", 0, "Float (Full)", "Full float (32 bit data)"}, /* default */
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static EnumPropertyItem fluid_mesh_quality_items[] = {
+ {FLUID_DOMAIN_MESH_IMPROVED,
+ "IMPROVED",
+ 0,
+ "Final",
+ "Use improved particle levelset (slower but more precise and with mesh smoothening "
+ "options)"},
+ {FLUID_DOMAIN_MESH_UNION,
+ "UNION",
+ 0,
+ "Preview",
+ "Use union particle levelset (faster but lower quality)"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static EnumPropertyItem fluid_guide_source_items[] = {
+ {FLUID_DOMAIN_GUIDE_SRC_DOMAIN,
+ "DOMAIN",
+ 0,
+ "Domain",
+ "Use a fluid domain for guiding (domain needs to be baked already so that velocities can "
+ "be extracted but can be of any type)"},
+ {FLUID_DOMAIN_GUIDE_SRC_EFFECTOR,
+ "EFFECTOR",
+ 0,
+ "Effector",
+ "Use guiding (effector) objects to create fluid guiding (guiding objects should be "
+ "animated and baked once set up completely)"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* Cache type - generated dynamically based on domain type */
+ static EnumPropertyItem cache_file_type_items[] = {
+ {0, "NONE", 0, "", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem view_items[] = {
+ {FLUID_DOMAIN_SLICE_VIEW_ALIGNED,
+ "VIEW_ALIGNED",
+ 0,
+ "View",
+ "Slice volume parallel to the view plane"},
+ {FLUID_DOMAIN_SLICE_AXIS_ALIGNED,
+ "AXIS_ALIGNED",
+ 0,
+ "Axis",
+ "Slice volume parallel to the major axis"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem axis_slice_method_items[] = {
+ {AXIS_SLICE_FULL, "FULL", 0, "Full", "Slice the whole domain object"},
+ {AXIS_SLICE_SINGLE, "SINGLE", 0, "Single", "Perform a single slice of the domain object"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem interp_method_item[] = {
+ {VOLUME_INTERP_LINEAR, "LINEAR", 0, "Linear", "Good smoothness and speed"},
+ {VOLUME_INTERP_CUBIC,
+ "CUBIC",
+ 0,
+ "Cubic",
+ "Smoothed high quality interpolation, but slower"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ 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, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem vector_draw_items[] = {
+ {VECTOR_DRAW_NEEDLE, "NEEDLE", 0, "Needle", "Display vectors as needles"},
+ {VECTOR_DRAW_STREAMLINE, "STREAMLINE", 0, "Streamlines", "Display vectors as streamlines"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem sndparticle_boundary_items[] = {
+ {SNDPARTICLE_BOUNDARY_DELETE,
+ "DELETE",
+ 0,
+ "Delete",
+ "Delete secondary particles that are inside obstacles or left the domain"},
+ {SNDPARTICLE_BOUNDARY_PUSHOUT,
+ "PUSHOUT",
+ 0,
+ "Push Out",
+ "Push secondary particles that left the domain back into the domain"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static const EnumPropertyItem sndparticle_combined_export_items[] = {
+ {SNDPARTICLE_COMBINED_EXPORT_OFF,
+ "OFF",
+ 0,
+ "Off",
+ "Create a seperate particle system for every secondary particle type"},
+ {SNDPARTICLE_COMBINED_EXPORT_SPRAY_FOAM,
+ "SPRAY_FOAM",
+ 0,
+ "Spray + Foam",
+ "Spray and foam particles are saved in the same particle system"},
+ {SNDPARTICLE_COMBINED_EXPORT_SPRAY_BUBBLE,
+ "SPRAY_BUBBLES",
+ 0,
+ "Spray + Bubbles",
+ "Spray and bubble particles are saved in the same particle system"},
+ {SNDPARTICLE_COMBINED_EXPORT_FOAM_BUBBLE,
+ "FOAM_BUBBLES",
+ 0,
+ "Foam + Bubbles",
+ "Foam and bubbles particles are saved in the same particle system"},
+ {SNDPARTICLE_COMBINED_EXPORT_SPRAY_FOAM_BUBBLE,
+ "SPRAY_FOAM_BUBBLES",
+ 0,
+ "Spray + Foam + Bubbles",
+ "Create one particle system that contains all three secondary particle types"},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem simulation_methods[] = {
+ {FLUID_DOMAIN_METHOD_FLIP, "FLIP", 0, "FLIP", "Use FLIP as the simulation method"},
+ /*{FLUID_DOMAIN_METHOD_APIC, "APIC", 0, "APIC", "Use APIC as the simulation method"},*/
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ srna = RNA_def_struct(brna, "FluidDomainSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Domain Settings", "Fluid domain settings");
+ RNA_def_struct_sdna(srna, "FluidDomainSettings");
+ RNA_def_struct_path_func(srna, "rna_FluidDomainSettings_path");
+
+ prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "EffectorWeights");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Effector Weights", "");
+
+ /* object collections */
+
+ prop = RNA_def_property(srna, "effector_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "effector_group");
+ RNA_def_property_struct_type(prop, "Collection");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Effector Collection", "Limit effectors to this collection");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset_dependency");
+
+ prop = RNA_def_property(srna, "fluid_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "fluid_group");
+ RNA_def_property_struct_type(prop, "Collection");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Fluid Collection", "Limit fluid objects to this collection");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset_dependency");
+
+ prop = RNA_def_property(srna, "force_collection", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "force_group");
+ RNA_def_property_struct_type(prop, "Collection");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Force Collection", "Limit forces to this collection");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset_dependency");
+
+ /* grid access */
+
+# ifdef WITH_FLUID
+ prop = RNA_def_property(srna, "density_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_FluidModifier_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_FluidModifier_density_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Density Grid", "Smoke density grid");
+
+ prop = RNA_def_property(srna, "velocity_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_FluidModifier_velocity_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_FluidModifier_velocity_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Velocity Grid", "Smoke velocity grid");
+
+ prop = RNA_def_property(srna, "flame_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_FluidModifier_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_FluidModifier_flame_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Flame Grid", "Smoke flame grid");
+
+ prop = RNA_def_property(srna, "color_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_FluidModifier_color_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_FluidModifier_color_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Color Grid", "Smoke color grid");
+
+ prop = RNA_def_property(srna, "heat_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_FluidModifier_heat_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_FluidModifier_heat_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Heat Grid", "Smoke heat grid");
+
+ prop = RNA_def_property(srna, "temperature_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_FluidModifier_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_FluidModifier_temperature_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(
+ prop, "Temperature Grid", "Smoke temperature grid, range 0..1 represents 0..1000K");
+# endif /* WITH_FLUID */
+
+ /* domain object data */
+
+ prop = RNA_def_property(srna,
+ "start_point",
+ PROP_FLOAT,
+ PROP_XYZ); /* can change each frame when using adaptive domain */
+ RNA_def_property_float_sdna(prop, NULL, "p0");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "p0", "Start point");
+
+ prop = RNA_def_property(srna,
+ "cell_size",
+ PROP_FLOAT,
+ PROP_XYZ); /* can change each frame when using adaptive domain */
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "cell_size", "Cell Size");
+
+ prop = RNA_def_property(srna,
+ "domain_resolution",
+ PROP_INT,
+ PROP_XYZ); /* can change each frame when using adaptive domain */
+ RNA_def_property_int_sdna(prop, NULL, "res");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "res", "Smoke Grid Resolution");
+
+ /* adaptive domain options */
+
+ prop = RNA_def_property(srna, "additional_res", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "adapt_res");
+ RNA_def_property_range(prop, 0, 512);
+ RNA_def_property_ui_text(prop, "Additional", "Maximum number of additional cells");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "adapt_margin", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "adapt_margin");
+ RNA_def_property_range(prop, 2, 24);
+ RNA_def_property_ui_text(
+ prop, "Margin", "Margin added around fluid to minimize boundary interference");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "adapt_threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.01, 0.5);
+ RNA_def_property_ui_text(
+ prop, "Threshold", "Maximum amount of fluid cell can contain before it is considered empty");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "use_adaptive_domain", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN);
+ RNA_def_property_ui_text(
+ prop, "Adaptive Domain", "Adapt simulation resolution and size to fluid");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ /* fluid domain options */
+
+ prop = RNA_def_property(srna, "resolution_max", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "maxres");
+ RNA_def_property_range(prop, 6, 10000);
+ RNA_def_property_ui_range(prop, 24, 10000, 2, -1);
+ RNA_def_property_ui_text(prop, "Max Res", "Resolution used for the fluid domain");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_collision_border_front", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_FRONT);
+ RNA_def_property_ui_text(prop, "Front", "Enable collisons with front domain border");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_collision_border_back", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_BACK);
+ RNA_def_property_ui_text(prop, "Back", "Enable collisons with back domain border");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_collision_border_right", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_RIGHT);
+ RNA_def_property_ui_text(prop, "Right", "Enable collisons with right domain border");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_collision_border_left", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_LEFT);
+ RNA_def_property_ui_text(prop, "Left", "Enable collisons with left domain border");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_collision_border_top", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_TOP);
+ RNA_def_property_ui_text(prop, "Top", "Enable collisons with top domain border");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_collision_border_bottom", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_BOTTOM);
+ RNA_def_property_ui_text(prop, "Bottom", "Enable collisons with bottom domain border");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION);
+ RNA_def_property_float_sdna(prop, NULL, "gravity");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, -1000.1, 1000.1);
+ RNA_def_property_ui_text(prop, "Gravity", "Gravity in X, Y and Z direction");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "domain_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, domain_types);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_domaintype_set", NULL);
+ RNA_def_property_ui_text(prop, "Domain Type", "Change domain type of the simulation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_reset");
+
+ /* smoke domain options */
+
+ prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "alpha");
+ RNA_def_property_range(prop, -5.0, 5.0);
+ RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
+ RNA_def_property_ui_text(
+ prop,
+ "Density",
+ "How much density affects smoke motion (higher value results in faster rising smoke)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "beta");
+ RNA_def_property_range(prop, -5.0, 5.0);
+ RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
+ RNA_def_property_ui_text(
+ prop,
+ "Heat",
+ "How much heat affects smoke motion (higher value results in faster rising smoke)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "diss_speed");
+ RNA_def_property_range(prop, 1.0, 10000.0);
+ RNA_def_property_ui_range(prop, 1.0, 10000.0, 1, -1);
+ RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vorticity");
+ RNA_def_property_range(prop, 0.0, 4.0);
+ RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence/rotation in fluid");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "highres_sampling", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, smoke_highres_sampling_items);
+ RNA_def_property_ui_text(prop, "Emitter", "Method for sampling the high resolution flow");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "use_dissolve_smoke", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_DISSOLVE);
+ RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "use_dissolve_smoke_log", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_DISSOLVE_LOG);
+ RNA_def_property_ui_text(prop, "Logarithmic dissolve", "Using 1/x ");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ /* flame options */
+
+ prop = RNA_def_property(srna, "burning_rate", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.01, 4.0);
+ RNA_def_property_ui_range(prop, 0.01, 2.0, 1.0, 5);
+ RNA_def_property_ui_text(
+ prop, "Speed", "Speed of the burning reaction (use larger values for smaller flame)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "flame_smoke", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 8.0);
+ RNA_def_property_ui_range(prop, 0.0, 4.0, 1.0, 5);
+ RNA_def_property_ui_text(prop, "Smoke", "Amount of smoke created by burning fuel");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "flame_vorticity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 2.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 5);
+ RNA_def_property_ui_text(prop, "Vorticity", "Additional vorticity for the flames");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "flame_ignition", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.5, 5.0);
+ RNA_def_property_ui_range(prop, 0.5, 2.5, 1.0, 5);
+ RNA_def_property_ui_text(prop, "Ignition", "Minimum temperature of flames");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "flame_max_temp", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 1.0, 10.0);
+ RNA_def_property_ui_range(prop, 1.0, 5.0, 1.0, 5);
+ RNA_def_property_ui_text(prop, "Maximum", "Maximum temperature of flames");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "flame_smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke emitted from burning fuel");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ /* noise options */
+
+ prop = RNA_def_property(srna, "noise_strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "noise_strength");
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 2);
+ RNA_def_property_ui_text(prop, "Strength", "Strength of noise");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "noise_pos_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "noise_pos_scale");
+ RNA_def_property_range(prop, 0.0001, 10.0);
+ RNA_def_property_ui_text(
+ prop, "Scale", "Scale of noise (higher value results in larger vortices)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "noise_time_anim", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "noise_time_anim");
+ RNA_def_property_range(prop, 0.0001, 10.0);
+ RNA_def_property_ui_text(prop, "Time", "Animation time of noise");
+
+ prop = RNA_def_property(srna, "noise_scale", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "noise_scale");
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_range(prop, 1, 10, 1, -1);
+ RNA_def_property_ui_text(prop,
+ "Noise Scale",
+ "Scale underlying noise grids by this factor. Noise grids have size "
+ "factor times base resolution");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "noise_type");
+ RNA_def_property_enum_items(prop, prop_noise_type_items);
+ RNA_def_property_ui_text(
+ prop, "Noise Method", "Noise method which is used for creating the high resolution");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_noise", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_NOISE);
+ RNA_def_property_ui_text(prop, "Use Noise", "Enable fluid noise (using amplification)");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_update");
+
+ /* liquid domain options */
+
+ prop = RNA_def_property(srna, "simulation_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "simulation_method");
+ RNA_def_property_enum_items(prop, simulation_methods);
+ RNA_def_property_ui_text(prop, "Simulation Method", "Change the underlying simulation method");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "flip_ratio", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(
+ prop,
+ "FLIP Ratio",
+ "PIC/FLIP Ratio. A value of 1.0 will result in a completely FLIP based simulation. Use a "
+ "lower value for simulations which should produce smaller splashes");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "particle_randomness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_text(prop, "Randomness", "Randomness factor for particle sampling");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "particle_number", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 5);
+ RNA_def_property_ui_text(
+ prop, "Number", "Particle number factor (higher value results in more particles)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "particle_min", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "particle_minimum");
+ RNA_def_property_range(prop, 0, 1000);
+ RNA_def_property_ui_text(prop,
+ "Minimum",
+ "Minimum number of particles per cell (ensures that each cell has at "
+ "least this amount of particles)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "particle_max", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "particle_maximum");
+ RNA_def_property_range(prop, 0, 1000);
+ RNA_def_property_ui_text(prop,
+ "Maximum",
+ "Maximum number of particles per cell (ensures that each cell has at "
+ "most this amount of particles)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "particle_radius", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_text(
+ prop,
+ "Radius",
+ "Particle radius factor. Use this parameter when the simulation appears to leak volume");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "particle_band_width", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(
+ prop,
+ "Width",
+ "Particle (narrow) band width (higher value results in thicker band and more particles)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "use_flip_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_FLIP);
+ RNA_def_property_ui_text(prop, "FLIP", "Create FLIP particle system");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Fluid_flip_parts_update");
+
+ prop = RNA_def_property(srna, "use_fractions", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_FRACTIONS);
+ RNA_def_property_ui_text(
+ prop,
+ "Fractional Obstacles",
+ "Fractional obstacles improve and smoothen the fluid-obstacle boundary");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "fractions_threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.001, 1.0);
+ RNA_def_property_ui_range(prop, 0.01, 1.0, 0.05, -1);
+ RNA_def_property_ui_text(prop,
+ "Obstacle-Fluid Threshold ",
+ "Determines how much fluid is allowed in an obstacle cell "
+ "(higher values will tag a boundary cell as an obstacle easier "
+ "and reduce the boundary smoothening effect)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ /* diffusion options */
+
+ prop = RNA_def_property(srna, "surface_tension", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_text(
+ prop,
+ "Tension",
+ "Surface tension of liquid (higher value results in greater hydrophobic behaviour)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "viscosity_base", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "viscosity_base");
+ RNA_def_property_range(prop, 0, 10);
+ RNA_def_property_ui_text(
+ prop,
+ "Viscosity Base",
+ "Viscosity setting: value that is multiplied by 10 to the power of (exponent*-1)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "viscosity_exponent", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "viscosity_exponent");
+ RNA_def_property_range(prop, 0, 10);
+ RNA_def_property_ui_text(
+ prop,
+ "Viscosity Exponent",
+ "Negative exponent for the viscosity value (to simplify entering small values "
+ "e.g. 5*10^-6)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "domain_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.001, 10000.0);
+ RNA_def_property_ui_text(prop, "Meters", "Domain size in meters (longest domain side)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ /* mesh options options */
+
+ prop = RNA_def_property(srna, "mesh_concave_upper", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_text(
+ prop,
+ "Upper Concavity",
+ "Upper mesh concavity bound (high values tend to smoothen and fill out concave regions)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "mesh_concave_lower", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_text(
+ prop,
+ "Lower Concavity",
+ "Lower mesh concavity bound (high values tend to smoothen and fill out concave regions)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "mesh_smoothen_pos", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Smoothen Pos", "Positive mesh smoothening");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "mesh_smoothen_neg", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Smoothen Neg", "Negative mesh smoothening");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "mesh_scale", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "mesh_scale");
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_range(prop, 1, 10, 1, -1);
+ RNA_def_property_ui_text(prop,
+ "Mesh scale",
+ "Scale underlying mesh grids by this factor. Mesh grids have size "
+ "factor times base resolution");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "mesh_generator", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mesh_generator");
+ RNA_def_property_enum_items(prop, fluid_mesh_quality_items);
+ RNA_def_property_ui_text(prop, "Mesh generator", "Which particle levelset generator to use");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update");
+
+ prop = RNA_def_property(srna, "mesh_vertices", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "mesh_velocities", "totvert");
+ RNA_def_property_struct_type(prop, "FluidDomainVertexVelocity");
+ RNA_def_property_ui_text(
+ prop, "Fluid Mesh Vertices", "Vertices of the fluid mesh generated by simulation");
+
+ rna_def_fluid_mesh_vertices(brna);
+
+ prop = RNA_def_property(srna, "use_mesh", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_MESH);
+ RNA_def_property_ui_text(prop, "Use Mesh", "Enable fluid mesh (using amplification)");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_update");
+
+ prop = RNA_def_property(srna, "use_speed_vectors", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_SPEED_VECTORS);
+ RNA_def_property_ui_text(
+ prop,
+ "Speed Vectors",
+ "Generate speed vectors (will be loaded automatically during render for motion blur)");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "mesh_particle_radius", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_text(
+ prop,
+ "Radius",
+ "Particle radius factor (higher value results in larger (meshed) particles)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ /* secondary particles options */
+
+ prop = RNA_def_property(srna, "sndparticle_tau_min_wc", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_range(prop, 0.0, 1000.0, 100.0, 3);
+ RNA_def_property_ui_text(prop,
+ "tauMin_wc",
+ "Lower clamping threshold for marking fluid cells as wave crests "
+ "(lower values result in more marked cells)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_tau_max_wc", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_range(prop, 0.0, 1000.0, 100.0, 3);
+ RNA_def_property_ui_text(prop,
+ "tauMax_wc",
+ "Upper clamping threshold for marking fluid cells as wave crests "
+ "(higher values result in less marked cells)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_tau_min_ta", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_range(prop, 0.0, 10000.0, 100.0, 3);
+ RNA_def_property_ui_text(prop,
+ "tauMin_ta",
+ "Lower clamping threshold for marking fluid cells where air is trapped "
+ "(lower values result in more marked cells)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_tau_max_ta", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_range(prop, 0.0, 1000.0, 100.0, 3);
+ RNA_def_property_ui_text(prop,
+ "tauMax_ta",
+ "Upper clamping threshold for marking fluid cells where air is trapped "
+ "(higher values result in less marked cells)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_tau_min_k", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_range(prop, 0.0, 1000.0, 100.0, 3);
+ RNA_def_property_ui_text(
+ prop,
+ "tauMin_k",
+ "Lower clamping threshold that indicates the fluid speed where cells start to emit "
+ "particles (lower values result in generally more particles)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_tau_max_k", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_range(prop, 0.0, 1000.0, 100.0, 3);
+ RNA_def_property_ui_text(
+ prop,
+ "tauMax_k",
+ "Upper clamping threshold that indicates the fluid speed where cells no longer emit more "
+ "particles (higher values result in generally less particles)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_k_wc", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 10000);
+ RNA_def_property_ui_range(prop, 0, 10000, 1.0, -1);
+ RNA_def_property_ui_text(prop,
+ "Wave Crest Sampling",
+ "Maximum number of particles generated per wave crest cell per frame");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_k_ta", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 10000);
+ RNA_def_property_ui_range(prop, 0, 10000, 1.0, -1);
+ RNA_def_property_ui_text(prop,
+ "Trapped Air Sampling",
+ "Maximum number of particles generated per trapped air cell per frame");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_k_b", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_range(prop, 0.0, 100.0, 10.0, 2);
+ RNA_def_property_ui_text(prop,
+ "Buoyancy",
+ "Amount of buoyancy force that rises bubbles (high values result in "
+ "bubble movement mainly upwards)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_k_d", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_range(prop, 0.0, 100.0, 10.0, 2);
+ RNA_def_property_ui_text(prop,
+ "Drag",
+ "Amount of drag force that moves bubbles along with the fluid (high "
+ "values result in bubble movement mainly along with the fluid)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_l_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10000.0);
+ RNA_def_property_ui_range(prop, 0.0, 10000.0, 100.0, 1);
+ RNA_def_property_ui_text(prop, "Lifetime(min)", "Lowest possible particle lifetime");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_l_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10000.0);
+ RNA_def_property_ui_range(prop, 0.0, 10000.0, 100.0, 1);
+ RNA_def_property_ui_text(prop, "Lifetime(max)", "Highest possible particle lifetime");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_boundary", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "sndparticle_boundary");
+ RNA_def_property_enum_items(prop, sndparticle_boundary_items);
+ RNA_def_property_ui_text(
+ prop, "Particles in Boundary", "How particles that left the domain are treated");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "sndparticle_combined_export", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "sndparticle_combined_export");
+ RNA_def_property_enum_items(prop, sndparticle_combined_export_items);
+ RNA_def_property_ui_text(
+ prop,
+ "Combined Export",
+ "Determines which particle systems are created from secondary particles");
+ RNA_def_property_update(prop, 0, "rna_Fluid_combined_export_update");
+
+ prop = RNA_def_property(srna, "sndparticle_potential_radius", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "sndparticle_potential_radius");
+ RNA_def_property_range(prop, 1, 4);
+ RNA_def_property_ui_range(prop, 1, 4, 1, -1);
+ RNA_def_property_ui_text(prop,
+ "Potential Radius",
+ "Radius to compute potential for each cell (higher values are slower "
+ "but create smoother potential grids)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "sndparticle_update_radius", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "sndparticle_update_radius");
+ RNA_def_property_range(prop, 1, 4);
+ RNA_def_property_ui_range(prop, 1, 4, 1, -1);
+ RNA_def_property_ui_text(prop,
+ "Update Radius",
+ "Radius to compute position update for each particle (higher values "
+ "are slower but particles move less chaotic)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "particle_scale", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "particle_scale");
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_range(prop, 1, 10, 1, -1);
+ RNA_def_property_ui_text(prop,
+ "Mesh scale",
+ "Scale underlying particle grids by this factor. Particle grids have "
+ "size factor times base resolution");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_spray_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_SPRAY);
+ RNA_def_property_ui_text(prop, "Spray", "Create spray particle system");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Fluid_spray_parts_update");
+
+ prop = RNA_def_property(srna, "use_bubble_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_BUBBLE);
+ RNA_def_property_ui_text(prop, "Bubble", "Create bubble particle system");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Fluid_bubble_parts_update");
+
+ prop = RNA_def_property(srna, "use_foam_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_FOAM);
+ RNA_def_property_ui_text(prop, "Foam", "Create foam particle system");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Fluid_foam_parts_update");
+
+ prop = RNA_def_property(srna, "use_tracer_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_TRACER);
+ RNA_def_property_ui_text(prop, "Tracer", "Create tracer particle system");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Fluid_tracer_parts_update");
+
+ /* fluid guiding options */
+
+ prop = RNA_def_property(srna, "guide_alpha", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "guide_alpha");
+ RNA_def_property_range(prop, 1.0, 100.0);
+ RNA_def_property_ui_text(prop, "Weight", "Guiding weight (higher value results in greater lag)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "guide_beta", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "guide_beta");
+ RNA_def_property_range(prop, 1, 50);
+ RNA_def_property_ui_text(prop, "Size", "Guiding size (higher value results in larger vortices)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "guide_vel_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "guide_vel_factor");
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_text(
+ prop,
+ "Weight",
+ "Guiding velocity factor (higher value results in bigger guiding velocities)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "guide_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "guide_source");
+ RNA_def_property_enum_items(prop, fluid_guide_source_items);
+ RNA_def_property_ui_text(prop, "Guiding source", "Choose where to get guiding velocities from");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update");
+
+ prop = RNA_def_property(srna, "guide_parent", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "guide_parent");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_Fluid_guide_parent_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop,
+ "",
+ "Use velocities from this object for the guiding effect (object needs "
+ "to have fluid modifier and be of type domain))");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update");
+
+ prop = RNA_def_property(srna, "use_guide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_GUIDE);
+ RNA_def_property_ui_text(prop, "Use Guiding", "Enable fluid guiding");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ /* cache options */
+
+ prop = RNA_def_property(srna, "cache_frame_start", PROP_INT, PROP_TIME);
+ RNA_def_property_int_sdna(prop, NULL, "cache_frame_start");
+ RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
+ RNA_def_property_ui_range(prop, 1, MAXFRAME, 1, 1);
+ RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts");
+
+ prop = RNA_def_property(srna, "cache_frame_end", PROP_INT, PROP_TIME);
+ RNA_def_property_int_sdna(prop, NULL, "cache_frame_end");
+ RNA_def_property_range(prop, 1, MAXFRAME);
+ RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops");
+
+ prop = RNA_def_property(srna, "cache_frame_pause_data", PROP_INT, PROP_TIME);
+ RNA_def_property_int_sdna(prop, NULL, "cache_frame_pause_data");
+
+ prop = RNA_def_property(srna, "cache_frame_pause_noise", PROP_INT, PROP_TIME);
+ RNA_def_property_int_sdna(prop, NULL, "cache_frame_pause_noise");
+
+ prop = RNA_def_property(srna, "cache_frame_pause_mesh", PROP_INT, PROP_TIME);
+ RNA_def_property_int_sdna(prop, NULL, "cache_frame_pause_mesh");
+
+ prop = RNA_def_property(srna, "cache_frame_pause_particles", PROP_INT, PROP_TIME);
+ RNA_def_property_int_sdna(prop, NULL, "cache_frame_pause_particles");
+
+ prop = RNA_def_property(srna, "cache_frame_pause_guide", PROP_INT, PROP_TIME);
+ RNA_def_property_int_sdna(prop, NULL, "cache_frame_pause_guide");
+
+ prop = RNA_def_property(srna, "cache_mesh_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "cache_mesh_format");
+ RNA_def_property_enum_items(prop, cache_file_type_items);
+ RNA_def_property_enum_funcs(
+ prop, NULL, "rna_Fluid_cachetype_mesh_set", "rna_Fluid_cachetype_mesh_itemf");
+ RNA_def_property_ui_text(
+ prop, "File Format", "Select the file format to be used for caching surface data");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "cache_data_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "cache_data_format");
+ RNA_def_property_enum_items(prop, cache_file_type_items);
+ RNA_def_property_enum_funcs(
+ prop, NULL, "rna_Fluid_cachetype_data_set", "rna_Fluid_cachetype_volume_itemf");
+ RNA_def_property_ui_text(
+ prop, "File Format", "Select the file format to be used for caching volumetric data");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "cache_particle_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "cache_particle_format");
+ RNA_def_property_enum_items(prop, cache_file_type_items);
+ RNA_def_property_enum_funcs(
+ prop, NULL, "rna_Fluid_cachetype_particle_set", "rna_Fluid_cachetype_particle_itemf");
+ RNA_def_property_ui_text(
+ prop, "File Format", "Select the file format to be used for caching particle data");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "cache_noise_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "cache_noise_format");
+ RNA_def_property_enum_items(prop, cache_file_type_items);
+ RNA_def_property_enum_funcs(
+ prop, NULL, "rna_Fluid_cachetype_noise_set", "rna_Fluid_cachetype_volume_itemf");
+ RNA_def_property_ui_text(
+ prop, "File Format", "Select the file format to be used for caching noise data");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "cache_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "cache_type");
+ RNA_def_property_enum_items(prop, cache_types);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_cachetype_set", NULL);
+ RNA_def_property_ui_text(prop, "Type", "Change the cache type of the simulation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "cache_directory", PROP_STRING, PROP_DIRPATH);
+ RNA_def_property_string_maxlength(prop, FILE_MAX);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Fluid_cache_directory_set");
+ RNA_def_property_string_sdna(prop, NULL, "cache_directory");
+ RNA_def_property_ui_text(prop, "Cache directory", "Directory that contains fluid cache files");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "is_cache_baking_data", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKING_DATA);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "has_cache_baked_data", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKED_DATA);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "is_cache_baking_noise", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKING_NOISE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "has_cache_baked_noise", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKED_NOISE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "is_cache_baking_mesh", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKING_MESH);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "has_cache_baked_mesh", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKED_MESH);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "is_cache_baking_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKING_PARTICLES);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "has_cache_baked_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKED_PARTICLES);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "is_cache_baking_guide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKING_GUIDE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "has_cache_baked_guide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKED_GUIDE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ /* Read only checks, avoids individually accessing flags above. */
+ prop = RNA_def_property(srna, "is_cache_baking_any", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKING_ALL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "has_cache_baked_any", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKED_ALL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "export_manta_script", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_EXPORT_MANTA_SCRIPT);
+ RNA_def_property_ui_text(
+ prop,
+ "Export Fluidflow Script",
+ "Generate and export Fluidflow script from current domain settings during bake. This is "
+ "only needed if you plan to analyse the cache (e.g. view grids, velocity vectors, "
+ "particles) in Fluidflow directly (outside of Blender) after baking the simulation");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ /* time options */
+
+ 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.0001, 10.0);
+ RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "cfl_condition", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "cfl_condition");
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_text(
+ prop, "CFL", "Maximal velocity per cell (higher value results in larger timesteps)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "use_adaptive_timesteps", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_ADAPTIVE_TIME);
+ RNA_def_property_ui_text(prop, "Use Adaptive Time Steps", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+
+ prop = RNA_def_property(srna, "timesteps_min", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "timesteps_minimum");
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_range(prop, 0, 100, 1, -1);
+ RNA_def_property_ui_text(
+ prop, "Minimum", "Minimum number of simulation steps to perform for one frame");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "timesteps_max", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "timesteps_maximum");
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_range(prop, 0, 100, 1, -1);
+ RNA_def_property_ui_text(
+ prop, "Maximum", "Maximum number of simulation steps to perform for one frame");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ /* display settings */
+
+ prop = RNA_def_property(srna, "slice_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "slice_method");
+ RNA_def_property_enum_items(prop, view_items);
+ RNA_def_property_ui_text(prop, "View Method", "How to slice the volume for viewport rendering");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "axis_slice_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "axis_slice_method");
+ RNA_def_property_enum_items(prop, axis_slice_method_items);
+ RNA_def_property_ui_text(prop, "Method", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ 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_ui_text(prop, "Axis", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "slice_per_voxel", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "slice_per_voxel");
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_range(prop, 0.0, 5.0, 0.1, 1);
+ RNA_def_property_ui_text(
+ prop, "Slice Per Voxel", "How many slices per voxel should be generated");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "slice_depth", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "slice_depth");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Position", "Position of the slice");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "display_thickness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "display_thickness");
+ RNA_def_property_range(prop, 0.001, 1000.0);
+ RNA_def_property_ui_range(prop, 0.1, 100.0, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Thickness", "Thickness of smoke drawing in the viewport");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ prop = RNA_def_property(srna, "display_interpolation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "interp_method");
+ RNA_def_property_enum_items(prop, interp_method_item);
+ RNA_def_property_ui_text(
+ prop, "Interpolation", "Interpolation method to use for smoke/fire volumes in solid mode");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "show_velocity", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "draw_velocity", 0);
+ RNA_def_property_ui_text(
+ prop, "Display Velocity", "Toggle visualization of the velocity field as needles");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "vector_display_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "vector_draw_type");
+ RNA_def_property_enum_items(prop, vector_draw_items);
+ RNA_def_property_ui_text(prop, "Display Type", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "vector_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vector_scale");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Scale", "Multiplier for scaling the vectors");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ /* --------- Color mapping. --------- */
+
+ prop = RNA_def_property(srna, "use_color_ramp", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "use_coba", 0);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_Fluid_use_color_ramp_set");
+ RNA_def_property_ui_text(
+ prop,
+ "Use Color Ramp",
+ "Render a simulation field while mapping its voxels values to the colors of a ramp");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ static const EnumPropertyItem coba_field_items[] = {
+ {FLUID_DOMAIN_FIELD_COLOR_R, "COLOR_R", 0, "Red", "Red component of the color field"},
+ {FLUID_DOMAIN_FIELD_COLOR_G, "COLOR_G", 0, "Green", "Green component of the color field"},
+ {FLUID_DOMAIN_FIELD_COLOR_B, "COLOR_B", 0, "Blue", "Blue component of the color field"},
+ {FLUID_DOMAIN_FIELD_DENSITY, "DENSITY", 0, "Density", "Quantity of soot in the fluid"},
+ {FLUID_DOMAIN_FIELD_FLAME, "FLAME", 0, "Flame", "Flame field"},
+ {FLUID_DOMAIN_FIELD_FUEL, "FUEL", 0, "Fuel", "Fuel field"},
+ {FLUID_DOMAIN_FIELD_HEAT, "HEAT", 0, "Heat", "Temperature of the fluid"},
+ {FLUID_DOMAIN_FIELD_VELOCITY_X,
+ "VELOCITY_X",
+ 0,
+ "X Velocity",
+ "X component of the velocity field"},
+ {FLUID_DOMAIN_FIELD_VELOCITY_Y,
+ "VELOCITY_Y",
+ 0,
+ "Y Velocity",
+ "Y component of the velocity field"},
+ {FLUID_DOMAIN_FIELD_VELOCITY_Z,
+ "VELOCITY_Z",
+ 0,
+ "Z Velocity",
+ "Z component of the velocity field"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ prop = RNA_def_property(srna, "coba_field", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "coba_field");
+ RNA_def_property_enum_items(prop, coba_field_items);
+ RNA_def_property_ui_text(prop, "Field", "Simulation field to color map");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "coba");
+ RNA_def_property_struct_type(prop, "ColorRamp");
+ RNA_def_property_ui_text(prop, "Color Ramp", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "clipping", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "clipping");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3);
+ RNA_def_property_ui_text(
+ prop,
+ "Clipping",
+ "Value under which voxels are considered empty space to optimize caching and rendering");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
+ /* -- Deprecated / unsed options (below)-- */
+
+ /* pointcache options */
+
+ prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "point_cache[0]");
+ RNA_def_property_struct_type(prop, "PointCache");
+ RNA_def_property_ui_text(prop, "Point Cache", "");
+
+ prop = RNA_def_property(srna, "point_cache_compress_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "cache_comp");
+ RNA_def_property_enum_items(prop, cache_comp_items);
+ RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
+
+ /* OpenVDB options */
+
+ prop = RNA_def_property(srna, "openvdb_cache_compress_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "openvdb_comp");
+ RNA_def_property_enum_items(prop, prop_compression_items);
+ RNA_def_property_ui_text(prop, "Compression", "Compression method to be used");
+
+ prop = RNA_def_property(srna, "data_depth", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "data_depth");
+ RNA_def_property_enum_items(prop, smoke_data_depth_items);
+ RNA_def_property_ui_text(prop,
+ "Data Depth",
+ "Bit depth for writing all scalar (including vector) "
+ "lower values reduce file size");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+}
+
+static void rna_def_fluid_flow_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem flow_types[] = {
+ {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"},
+ {FLUID_FLOW_TYPE_LIQUID, "LIQUID", 0, "Liquid", "Add liquid"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static EnumPropertyItem flow_behaviors[] = {
+ {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,
+ "GEOMETRY",
+ 0,
+ "Geometry",
+ "Only use given geometry for fluid"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* Flow source - generated dynamically based on flow type */
+ static EnumPropertyItem flow_sources[] = {
+ {0, "NONE", 0, "", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem flow_texture_types[] = {
+ {FLUID_FLOW_TEXTURE_MAP_AUTO,
+ "AUTO",
+ 0,
+ "Generated",
+ "Generated coordinates centered to flow object"},
+ {FLUID_FLOW_TEXTURE_MAP_UV, "UV", 0, "UV", "Use UV layer for texture coordinates"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ srna = RNA_def_struct(brna, "FluidFlowSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Flow Settings", "Fluid flow settings");
+ RNA_def_struct_sdna(srna, "FluidFlowSettings");
+ RNA_def_struct_path_func(srna, "rna_FluidFlowSettings_path");
+
+ prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "density");
+ RNA_def_property_range(prop, 0.0, 1);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 4);
+ RNA_def_property_ui_text(prop, "Density", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "color");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "fuel_amount", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10);
+ RNA_def_property_ui_range(prop, 0.0, 5.0, 1.0, 4);
+ RNA_def_property_ui_text(prop, "Flame Rate", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "temperature", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "temperature");
+ RNA_def_property_range(prop, -10, 10);
+ RNA_def_property_ui_range(prop, -10, 10, 1, 1);
+ RNA_def_property_ui_text(prop, "Temp. Diff.", "Temperature difference to ambient temperature");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "psys");
+ RNA_def_property_struct_type(prop, "ParticleSystem");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object");
+ RNA_def_property_update(prop, 0, "rna_Fluid_reset_dependency");
+
+ 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_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_ui_text(prop, "Flow Behavior", "Change flow behavior in the simulation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "flow_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "source");
+ RNA_def_property_enum_items(prop, flow_sources);
+ RNA_def_property_enum_funcs(
+ prop, NULL, "rna_Fluid_flowsource_set", "rna_Fluid_flowsource_itemf");
+ RNA_def_property_ui_text(prop, "Source", "Change how fluid is emitted");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_absolute", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_ABSOLUTE);
+ RNA_def_property_ui_text(prop,
+ "Absolute Density",
+ "Only allow given density value in emitter area and will not add up");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_initial_velocity", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_INITVELOCITY);
+ RNA_def_property_ui_text(
+ prop, "Initial Velocity", "Fluid has some initial velocity when it is emitted");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vel_multi");
+ RNA_def_property_range(prop, -100.0, 100.0);
+ RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
+ RNA_def_property_ui_text(prop,
+ "Source",
+ "Multiplier of source velocity passed to fluid (source velocity is "
+ "non-zero only if object is moving)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "velocity_normal", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vel_normal");
+ RNA_def_property_range(prop, -100.0, 100.0);
+ RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
+ RNA_def_property_ui_text(prop, "Normal", "Amount of normal directional velocity");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "velocity_random", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vel_random");
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_range(prop, 0.0, 2.0, 0.05, 5);
+ RNA_def_property_ui_text(prop, "Random", "Amount of random velocity");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "velocity_coord", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "vel_coord");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, -1000.1, 1000.1);
+ RNA_def_property_ui_text(prop, "Initial", "Initial velocity in X, Y and Z direction");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "volume_density", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.05, 5);
+ RNA_def_property_ui_text(prop, "Volume", "Factor for smoke emitted from inside the mesh volume");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_range(prop, 0.0, 10.0, 0.05, 5);
+ RNA_def_property_ui_text(prop, "Surface", "Maximum distance from mesh surface to emit fluid");
+ 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_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");
+
+ prop = RNA_def_property(srna, "particle_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.1, 20.0);
+ RNA_def_property_ui_range(prop, 0.5, 5.0, 0.05, 5);
+ RNA_def_property_ui_text(prop, "Size", "Particle size in simulation cells");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_particle_size", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_PART_SIZE);
+ RNA_def_property_ui_text(
+ prop, "Set Size", "Set particle size in simulation cells or use nearest cell");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_inflow", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_INFLOW);
+ RNA_def_property_ui_text(prop, "Enabled", "Control when to apply inflow");
+ 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 flows");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "density_vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop,
+ "rna_FluidFlow_density_vgroup_get",
+ "rna_FluidFlow_density_vgroup_length",
+ "rna_FluidFlow_density_vgroup_set");
+ RNA_def_property_ui_text(
+ prop, "Vertex Group", "Name of vertex group which determines surface emission rate");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "use_texture", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_TEXTUREEMIT);
+ RNA_def_property_ui_text(prop, "Use Texture", "Use a texture to control emission strength");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "texture_map_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "texture_type");
+ RNA_def_property_enum_items(prop, flow_texture_types);
+ RNA_def_property_ui_text(prop, "Mapping", "Texture mapping type");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "uvlayer_name");
+ RNA_def_property_ui_text(prop, "UV Map", "UV map name");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_FluidFlow_uvlayer_set");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "noise_texture", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Texture", "Texture that controls emission strength");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "texture_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.01, 10.0);
+ RNA_def_property_ui_range(prop, 0.1, 5.0, 0.05, 5);
+ RNA_def_property_ui_text(prop, "Size", "Size of texture mapping");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "texture_offset", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 200.0);
+ RNA_def_property_ui_range(prop, 0.0, 100.0, 0.05, 5);
+ RNA_def_property_ui_text(prop, "Offset", "Z-offset of texture mapping");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+}
+
+static void rna_def_fluid_effector_settings(BlenderRNA *brna)
+{
+ static EnumPropertyItem effector_type_items[] = {
+ {FLUID_EFFECTOR_TYPE_COLLISION, "COLLISION", 0, "Collision", "Create collision object"},
+ {FLUID_EFFECTOR_TYPE_GUIDE, "GUIDE", 0, "Guide", "Create guide object"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static EnumPropertyItem fluid_guide_mode_items[] = {
+ {FLUID_EFFECTOR_GUIDE_MAX,
+ "MAXIMUM",
+ 0,
+ "Maximize",
+ "Compare velocities from previous frame with new velocities from current frame and keep "
+ "the maximum"},
+ {FLUID_EFFECTOR_GUIDE_MIN,
+ "MINIMUM",
+ 0,
+ "Minimize",
+ "Compare velocities from previous frame with new velocities from current frame and keep "
+ "the minimum"},
+ {FLUID_EFFECTOR_GUIDE_OVERRIDE,
+ "OVERRIDE",
+ 0,
+ "Override",
+ "Always write new guide velocities for every frame (each frame only contains current "
+ "velocities from guiding objects)"},
+ {FLUID_EFFECTOR_GUIDE_AVERAGED,
+ "AVERAGED",
+ 0,
+ "Averaged",
+ "Take average of velocities from previous frame and new velocities from current frame"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "FluidEffectorSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Effector Settings", "Smoke collision settings");
+ RNA_def_struct_sdna(srna, "FluidEffectorSettings");
+ RNA_def_struct_path_func(srna, "rna_FluidEffectorSettings_path");
+
+ prop = RNA_def_property(srna, "effector_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, effector_type_items);
+ RNA_def_property_ui_text(prop, "Effector Type", "Change type of effector in the simulation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 10.0);
+ RNA_def_property_ui_range(prop, 0.0, 10.0, 0.05, 5);
+ RNA_def_property_ui_text(
+ prop, "Surface", "Distance around mesh surface to consider as effector");
+ 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_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");
+
+ prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vel_multi");
+ RNA_def_property_range(prop, -100.0, 100.0);
+ RNA_def_property_ui_text(prop, "Source", "Multiplier of obstacle velocity");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+
+ prop = RNA_def_property(srna, "guide_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "guide_mode");
+ 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");
+}
+
+void RNA_def_fluid(BlenderRNA *brna)
+{
+ rna_def_fluid_domain_settings(brna);
+ rna_def_fluid_flow_settings(brna);
+ rna_def_fluid_effector_settings(brna);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
deleted file mode 100644
index 2f09b90a81e..00000000000
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/** \file
- * \ingroup RNA
- */
-
-#include <stdlib.h>
-
-#include "DNA_object_fluidsim_types.h"
-
-#include "BLI_threads.h"
-#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
-
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#ifdef RNA_RUNTIME
-
-# include "MEM_guardedalloc.h"
-
-# include "DNA_scene_types.h"
-# include "DNA_particle_types.h"
-
-# include "BKE_fluidsim.h"
-# include "BKE_global.h"
-# include "BKE_main.h"
-# include "BKE_modifier.h"
-# include "BKE_particle.h"
-# include "BKE_pointcache.h"
-
-# include "DEG_depsgraph.h"
-
-static StructRNA *rna_FluidSettings_refine(struct PointerRNA *ptr)
-{
- FluidsimSettings *fss = (FluidsimSettings *)ptr->data;
-
- switch (fss->type) {
- case OB_FLUIDSIM_DOMAIN:
- return &RNA_DomainFluidSettings;
- case OB_FLUIDSIM_FLUID:
- return &RNA_FluidFluidSettings;
- case OB_FLUIDSIM_OBSTACLE:
- return &RNA_ObstacleFluidSettings;
- case OB_FLUIDSIM_INFLOW:
- return &RNA_InflowFluidSettings;
- case OB_FLUIDSIM_OUTFLOW:
- return &RNA_OutflowFluidSettings;
- case OB_FLUIDSIM_PARTICLE:
- return &RNA_ParticleFluidSettings;
- case OB_FLUIDSIM_CONTROL:
- return &RNA_ControlFluidSettings;
- default:
- return &RNA_FluidSettings;
- }
-}
-
-static void rna_fluid_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->owner_id;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
-}
-
-static int fluidsim_find_lastframe(Main *bmain, Object *ob, FluidsimSettings *fss)
-{
- char targetFileTest[FILE_MAX];
- char targetFile[FILE_MAX];
- int curFrame = 1;
-
- BLI_join_dirfile(
- targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
- BLI_path_abs(targetFile, modifier_path_relbase(bmain, ob));
-
- do {
- BLI_strncpy(targetFileTest, targetFile, sizeof(targetFileTest));
- BLI_path_frame(targetFileTest, curFrame++, 0);
- } while (BLI_exists(targetFileTest));
-
- return curFrame - 1;
-}
-
-static void rna_fluid_find_enframe(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->owner_id;
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
- ob, eModifierType_Fluidsim);
-
- if (fluidmd->fss->flag & OB_FLUIDSIM_REVERSE) {
- fluidmd->fss->lastgoodframe = fluidsim_find_lastframe(bmain, ob, fluidmd->fss);
- }
- else {
- fluidmd->fss->lastgoodframe = -1;
- }
- rna_fluid_update(bmain, scene, ptr);
-}
-
-static void rna_FluidSettings_update_type(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->owner_id;
- FluidsimModifierData *fluidmd;
- ParticleSystemModifierData *psmd;
- ParticleSystem *psys, *next_psys;
- ParticleSettings *part;
-
- fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- fluidmd->fss->flag &= ~OB_FLUIDSIM_REVERSE; /* clear flag */
-
- /* remove fluidsim particle system */
- if (fluidmd->fss->type & OB_FLUIDSIM_PARTICLE) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys->part->type == PART_FLUID) {
- break;
- }
- }
-
- if (ob->type == OB_MESH && !psys) {
- /* add particle system */
- part = BKE_particlesettings_add(bmain, "ParticleSettings");
- psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
-
- part->type = PART_FLUID;
- psys->part = part;
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- BLI_strncpy(psys->name, "FluidParticles", sizeof(psys->name));
- BLI_addtail(&ob->particlesystem, psys);
-
- /* add modifier */
- psmd = (ParticleSystemModifierData *)modifier_new(eModifierType_ParticleSystem);
- BLI_strncpy(psmd->modifier.name, "FluidParticleSystem", sizeof(psmd->modifier.name));
- psmd->psys = psys;
- BLI_addtail(&ob->modifiers, psmd);
- modifier_unique_name(&ob->modifiers, (ModifierData *)psmd);
- }
- }
- else {
- for (psys = ob->particlesystem.first; psys; psys = next_psys) {
- next_psys = psys->next;
- if (psys->part->type == PART_FLUID) {
- /* clear modifier */
- psmd = psys_get_modifier(ob, psys);
- BLI_remlink(&ob->modifiers, psmd);
- modifier_free((ModifierData *)psmd);
-
- /* clear particle system */
- BLI_remlink(&ob->particlesystem, psys);
- psys_free(ob, psys);
- }
- }
- }
-
- rna_fluid_update(bmain, scene, ptr);
-}
-
-static void rna_DomainFluidSettings_memory_estimate_get(PointerRNA *ptr, char *value)
-{
-# ifndef WITH_MOD_FLUID
- (void)ptr;
- value[0] = '\0';
-# else
- Object *ob = (Object *)ptr->owner_id;
- FluidsimSettings *fss = (FluidsimSettings *)ptr->data;
-
- fluid_estimate_memory(ob, fss, value);
-# endif
-}
-
-static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *ptr)
-{
-# ifndef WITH_MOD_FLUID
- UNUSED_VARS(ptr);
- return 0;
-# else
- char value[32];
-
- rna_DomainFluidSettings_memory_estimate_get(ptr, value);
- return strlen(value);
-# endif
-}
-
-static char *rna_FluidSettings_path(PointerRNA *ptr)
-{
- FluidsimSettings *fss = (FluidsimSettings *)ptr->data;
- ModifierData *md = (ModifierData *)fss->fmd;
- char name_esc[sizeof(md->name) * 2];
-
- BLI_strescape(name_esc, md->name, sizeof(name_esc));
- return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc);
-}
-
-#else
-
-static void rna_def_fluidsim_slip(StructRNA *srna)
-{
- PropertyRNA *prop;
-
- static const EnumPropertyItem slip_items[] = {
- {OB_FSBND_NOSLIP,
- "NOSLIP",
- 0,
- "No Slip",
- "Obstacle causes zero normal and tangential velocity (=sticky), default for all "
- "(only option for moving objects)"},
- {OB_FSBND_PARTSLIP,
- "PARTIALSLIP",
- 0,
- "Partial Slip",
- "Mix between no-slip and free-slip (non moving objects only!)"},
- {OB_FSBND_FREESLIP,
- "FREESLIP",
- 0,
- "Free Slip",
- "Obstacle only causes zero normal velocity (=not sticky, non moving objects only!)"},
- {0, NULL, 0, NULL, NULL},
- };
-
- prop = RNA_def_property(srna, "slip_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "typeFlags");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_items(prop, slip_items);
- RNA_def_property_ui_text(prop, "Slip Type", "");
-
- prop = RNA_def_property(srna, "partial_slip_factor", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "partSlipValue");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(
- prop,
- "Partial Slip Amount",
- "Amount of mixing between no- and free-slip, 0 is no slip and 1 is free slip");
-}
-
-static void rna_def_fluid_mesh_vertices(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "FluidVertexVelocity", NULL);
- RNA_def_struct_ui_text(srna, "Fluid Mesh Velocity", "Velocity of a simulated fluid mesh");
- RNA_def_struct_ui_icon(srna, ICON_VERTEXSEL);
-
- prop = RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_array(prop, 3);
- RNA_def_property_float_sdna(prop, NULL, "vel");
- RNA_def_property_ui_text(prop, "Velocity", "");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-}
-
-static void rna_def_fluidsim_domain(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static const EnumPropertyItem quality_items[] = {
- {OB_FSDOM_GEOM, "GEOMETRY", 0, "Geometry", "Display geometry"},
- {OB_FSDOM_PREVIEW, "PREVIEW", 0, "Preview", "Display preview quality results"},
- {OB_FSDOM_FINAL, "FINAL", 0, "Final", "Display final quality results"},
- {0, NULL, 0, NULL, NULL},
- };
-
- srna = RNA_def_struct(brna, "DomainFluidSettings", "FluidSettings");
- RNA_def_struct_sdna(srna, "FluidsimSettings");
- RNA_def_struct_ui_text(srna,
- "Domain Fluid Simulation Settings",
- "Fluid simulation settings for the domain of a fluid simulation");
-
- /* standard settings */
-
- prop = RNA_def_property(srna, "threads", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "threads");
- RNA_def_property_range(prop, 0, BLENDER_MAX_THREADS);
- RNA_def_property_ui_text(
- prop, "Simulation Threads", "Override number of threads for the simulation, 0 is automatic");
-
- prop = RNA_def_property(srna, "resolution", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "resolutionxyz");
- RNA_def_property_range(prop, 1, 1024);
- RNA_def_property_ui_text(prop, "Resolution", "Domain resolution in X,Y and Z direction");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-
- prop = RNA_def_property(srna, "preview_resolution", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "previewresxyz");
- RNA_def_property_range(prop, 1, 100);
- RNA_def_property_ui_text(
- prop, "Preview Resolution", "Preview resolution in X,Y and Z direction");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-
- prop = RNA_def_property(srna, "viewport_display_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "guiDisplayMode");
- RNA_def_property_enum_items(prop, quality_items);
- RNA_def_property_ui_text(
- prop, "Viewport Display Mode", "How to display the mesh in the viewport");
- RNA_def_property_update(prop, 0, "rna_fluid_update");
-
- prop = RNA_def_property(srna, "render_display_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "renderDisplayMode");
- RNA_def_property_enum_items(prop, quality_items);
- RNA_def_property_ui_text(prop, "Render Display Mode", "How to display the mesh for rendering");
-
- prop = RNA_def_property(srna, "use_reverse_frames", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", OB_FLUIDSIM_REVERSE);
- RNA_def_property_ui_text(prop, "Reverse Frames", "Reverse fluid frames");
- RNA_def_property_update(prop, 0, "rna_fluid_find_enframe");
-
- prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
- RNA_def_property_string_maxlength(prop, FILE_MAX);
- RNA_def_property_string_sdna(prop, NULL, "surfdataPath");
- RNA_def_property_ui_text(
- prop, "Path", "Directory (and/or filename prefix) to store baked fluid simulation files in");
- RNA_def_property_update(prop, 0, "rna_fluid_update");
-
- prop = RNA_def_property(srna, "memory_estimate", PROP_STRING, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_string_funcs(prop,
- "rna_DomainFluidSettings_memory_estimate_get",
- "rna_DomainFluidSettings_memory_estimate_length",
- NULL);
- RNA_def_property_ui_text(
- prop, "Memory Estimate", "Estimated amount of memory needed for baking the domain");
-
- /* advanced settings */
- prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION);
- RNA_def_property_float_sdna(prop, NULL, "grav");
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, -1000.1, 1000.1);
- RNA_def_property_ui_text(prop, "Gravity", "Gravity in X, Y and Z direction");
-
- prop = RNA_def_property(srna, "use_time_override", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", OB_FLUIDSIM_OVERRIDE_TIME);
- RNA_def_property_ui_text(
- prop,
- "Override Time",
- "Use a custom start and end time (in seconds) instead of the scene's timeline");
-
- prop = RNA_def_property(srna, "start_time", PROP_FLOAT, PROP_TIME);
- RNA_def_property_float_sdna(prop, NULL, "animStart");
- RNA_def_property_range(prop, 0, FLT_MAX);
- RNA_def_property_ui_text(
- prop, "Start Time", "Simulation time of the first blender frame (in seconds)");
-
- prop = RNA_def_property(srna, "end_time", PROP_FLOAT, PROP_TIME);
- RNA_def_property_float_sdna(prop, NULL, "animEnd");
- RNA_def_property_range(prop, 0, FLT_MAX);
- RNA_def_property_ui_text(
- prop, "End Time", "Simulation time of the last blender frame (in seconds)");
-
- prop = RNA_def_property(srna, "frame_offset", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "frameOffset");
- RNA_def_property_ui_text(prop, "Cache Offset", "Offset when reading baked cache");
- RNA_def_property_update(prop, NC_OBJECT, "rna_fluid_update");
-
- prop = RNA_def_property(srna, "simulation_scale", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "realsize");
- RNA_def_property_range(prop, 0.001, 10);
- RNA_def_property_ui_text(prop, "Real World Size", "Size of the simulation domain in meters");
-
- 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_base", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "viscosityValue");
- RNA_def_property_range(prop, 0, 10);
- RNA_def_property_ui_text(
- prop,
- "Viscosity Base",
- "Viscosity setting: value that is multiplied by 10 to the power of (exponent*-1)");
-
- prop = RNA_def_property(srna, "viscosity_exponent", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "viscosityExponent");
- RNA_def_property_range(prop, 0, 10);
- RNA_def_property_ui_text(
- prop,
- "Viscosity Exponent",
- "Negative exponent for the viscosity value (to simplify entering small values "
- "e.g. 5*10^-6)");
-
- prop = RNA_def_property(srna, "grid_levels", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "maxRefine");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, -1, 4);
- RNA_def_property_ui_text(
- prop, "Grid Levels", "Number of coarsened grids to use (-1 for automatic)");
-
- prop = RNA_def_property(srna, "compressibility", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "gstar");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0.001, 0.1);
- RNA_def_property_ui_text(prop,
- "Compressibility",
- "Allowed compressibility due to gravitational force for standing fluid "
- "(directly affects simulation step size)");
-
- /* domain boundary settings */
-
- rna_def_fluidsim_slip(srna);
-
- prop = RNA_def_property(srna, "surface_smooth", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "surfaceSmoothing");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0.0, 5.0);
- RNA_def_property_ui_text(
- prop,
- "Surface Smoothing",
- "Amount of surface smoothing (a value of 0 is off, 1 is normal smoothing and "
- "more than 1 is extra smoothing)");
-
- prop = RNA_def_property(srna, "surface_subdivisions", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "surfaceSubdivs");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0, 5);
- RNA_def_property_ui_text(
- prop,
- "Surface Subdivisions",
- "Number of isosurface subdivisions (this is necessary for the inclusion of particles "
- "into the surface generation - WARNING: can lead to longer computation times !)");
-
- prop = RNA_def_property(srna, "use_speed_vectors", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "domainNovecgen", 0);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(
- prop, "Generate Speed Vectors", "Generate speed vectors for vector blur");
-
- /* no collision object surface */
- prop = RNA_def_property(srna, "use_surface_noobs", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "typeFlags", OB_FSSG_NOOBS);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(
- prop,
- "Remove Air Bubbles",
- "Removes the air gap between fluid surface and obstacles - WARNING: Can result "
- "in a dissolving surface in other areas");
-
- /* particles */
-
- prop = RNA_def_property(srna, "tracer_particles", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "generateTracers");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0, 10000);
- RNA_def_property_ui_text(prop, "Tracer Particles", "Number of tracer particles to generate");
-
- prop = RNA_def_property(srna, "generate_particles", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "generateParticles");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(
- prop, "Generate Particles", "Amount of particles to generate (0=off, 1=normal, >1=more)");
-
- /* simulated fluid mesh data */
- prop = RNA_def_property(srna, "fluid_mesh_vertices", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "meshVelocities", "totvert");
- RNA_def_property_struct_type(prop, "FluidVertexVelocity");
- RNA_def_property_ui_text(
- prop, "Fluid Mesh Vertices", "Vertices of the fluid mesh generated by simulation");
-
- rna_def_fluid_mesh_vertices(brna);
-}
-
-static void rna_def_fluidsim_volume(StructRNA *srna)
-{
- PropertyRNA *prop;
-
- static const EnumPropertyItem volume_type_items[] = {
- {1, "VOLUME", 0, "Volume", "Use only the inner volume of the mesh"},
- {2, "SHELL", 0, "Shell", "Use only the outer shell of the mesh"},
- {3, "BOTH", 0, "Both", "Use both the inner volume and the outer shell of the mesh"},
- {0, NULL, 0, NULL, NULL},
- };
-
- prop = RNA_def_property(srna, "volume_initialization", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "volumeInitType");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_items(prop, volume_type_items);
- RNA_def_property_ui_text(
- prop,
- "Volume Initialization",
- "Volume initialization type "
- "(WARNING: complex volumes might require too much memory and break simulation)");
-
- prop = RNA_def_property(srna, "use_animated_mesh", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "domainNovecgen", 0);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(
- prop,
- "Export Animated Mesh",
- "Export this mesh as an animated one (slower and enforces No Slip, only use if really "
- "necessary [e.g. armatures or parented objects], animated pos/rot/scale F-Curves "
- "do not require it)");
-}
-
-static void rna_def_fluidsim_active(StructRNA *srna)
-{
- PropertyRNA *prop;
-
- prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", OB_FLUIDSIM_ACTIVE);
- RNA_def_property_ui_text(prop, "Enabled", "Object contributes to the fluid simulation");
-}
-
-static void rna_def_fluidsim_fluid(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "FluidFluidSettings", "FluidSettings");
- RNA_def_struct_sdna(srna, "FluidsimSettings");
- RNA_def_struct_ui_text(srna,
- "Fluid Fluid Simulation Settings",
- "Fluid simulation settings for the fluid in the simulation");
-
- rna_def_fluidsim_active(srna);
- rna_def_fluidsim_volume(srna);
-
- prop = RNA_def_property(srna, "initial_velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "iniVelx");
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, -1000.1, 1000.1);
- RNA_def_property_ui_text(prop, "Initial Velocity", "Initial velocity of fluid");
-}
-
-static void rna_def_fluidsim_obstacle(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ObstacleFluidSettings", "FluidSettings");
- RNA_def_struct_sdna(srna, "FluidsimSettings");
- RNA_def_struct_ui_text(srna,
- "Obstacle Fluid Simulation Settings",
- "Fluid simulation settings for obstacles in the simulation");
-
- rna_def_fluidsim_active(srna);
- rna_def_fluidsim_volume(srna);
- rna_def_fluidsim_slip(srna);
-
- prop = RNA_def_property(srna, "impact_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "surfaceSmoothing");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, -2.0, 10.0);
- RNA_def_property_ui_text(
- prop,
- "Impact Factor",
- "This is an unphysical value for moving objects - it controls the impact an obstacle "
- "has on the fluid, =0 behaves a bit like outflow (deleting fluid), =1 is default, "
- "while >1 results in high forces (can be used to tweak total mass)");
-}
-
-static void rna_def_fluidsim_inflow(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "InflowFluidSettings", "FluidSettings");
- RNA_def_struct_sdna(srna, "FluidsimSettings");
- RNA_def_struct_ui_text(srna,
- "Inflow Fluid Simulation Settings",
- "Fluid simulation settings for objects adding fluids in the simulation");
-
- rna_def_fluidsim_active(srna);
- rna_def_fluidsim_volume(srna);
-
- prop = RNA_def_property(srna, "inflow_velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "iniVelx");
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, -1000.1, 1000.1);
- RNA_def_property_ui_text(prop, "Inflow Velocity", "Initial velocity of fluid");
-
- prop = RNA_def_property(srna, "use_local_coords", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_boolean_sdna(prop, NULL, "typeFlags", OB_FSINFLOW_LOCALCOORD);
- RNA_def_property_ui_text(
- prop, "Local Coordinates", "Use local coordinates for inflow (e.g. for rotating objects)");
-}
-
-static void rna_def_fluidsim_outflow(BlenderRNA *brna)
-{
- StructRNA *srna;
-
- srna = RNA_def_struct(brna, "OutflowFluidSettings", "FluidSettings");
- RNA_def_struct_sdna(srna, "FluidsimSettings");
- RNA_def_struct_ui_text(
- srna,
- "Outflow Fluid Simulation Settings",
- "Fluid simulation settings for objects removing fluids from the simulation");
-
- rna_def_fluidsim_active(srna);
- rna_def_fluidsim_volume(srna);
-}
-
-static void rna_def_fluidsim_particle(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ParticleFluidSettings", "FluidSettings");
- RNA_def_struct_sdna(srna, "FluidsimSettings");
- RNA_def_struct_ui_text(srna,
- "Particle Fluid Simulation Settings",
- "Fluid simulation settings for objects storing fluid particles generated"
- " by the simulation");
-
- prop = RNA_def_property(srna, "use_drops", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "typeFlags", OB_FSPART_DROP);
- RNA_def_property_ui_text(prop, "Drops", "Show drop particles");
-
- prop = RNA_def_property(srna, "use_floats", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "typeFlags", OB_FSPART_FLOAT);
- RNA_def_property_ui_text(prop, "Floats", "Show floating foam particles");
-
- prop = RNA_def_property(srna, "show_tracer", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "typeFlags", OB_FSPART_TRACER);
- RNA_def_property_ui_text(prop, "Tracer", "Show tracer particles");
-
- prop = RNA_def_property(srna, "particle_influence", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "particleInfSize");
- RNA_def_property_range(prop, 0.0, 2.0);
- RNA_def_property_ui_text(
- prop,
- "Particle Influence",
- "Amount of particle size scaling: 0=off (all same size), 1=full (range 0.2-2.0), "
- ">1=stronger");
-
- prop = RNA_def_property(srna, "alpha_influence", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "particleInfAlpha");
- RNA_def_property_range(prop, 0.0, 2.0);
- RNA_def_property_ui_text(
- prop,
- "Alpha Influence",
- "Amount of particle alpha change, inverse of size influence: 0=off (all same alpha), "
- "1=full (larger particles get lower alphas, smaller ones higher values)");
-
- prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
- RNA_def_property_string_maxlength(prop, FILE_MAX);
- RNA_def_property_string_sdna(prop, NULL, "surfdataPath");
- RNA_def_property_ui_text(
- prop, "Path", "Directory (and/or filename prefix) to store and load particles from");
- RNA_def_property_update(prop, 0, "rna_fluid_update");
-}
-
-static void rna_def_fluidsim_control(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ControlFluidSettings", "FluidSettings");
- RNA_def_struct_sdna(srna, "FluidsimSettings");
- RNA_def_struct_ui_text(
- srna,
- "Control Fluid Simulation Settings",
- "Fluid simulation settings for objects controlling the motion of fluid in the simulation");
-
- rna_def_fluidsim_active(srna);
-
- prop = RNA_def_property(srna, "start_time", PROP_FLOAT, PROP_TIME);
- RNA_def_property_float_sdna(prop, NULL, "cpsTimeStart");
- RNA_def_property_range(prop, 0.0, FLT_MAX);
- RNA_def_property_ui_text(prop, "Start Time", "Time when the control particles are activated");
-
- prop = RNA_def_property(srna, "end_time", PROP_FLOAT, PROP_TIME);
- RNA_def_property_float_sdna(prop, NULL, "cpsTimeEnd");
- RNA_def_property_range(prop, 0.0, FLT_MAX);
- RNA_def_property_ui_text(prop, "End Time", "Time when the control particles are deactivated");
-
- prop = RNA_def_property(srna, "attraction_strength", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "attractforceStrength");
- RNA_def_property_range(prop, -10.0, 10.0);
- RNA_def_property_ui_text(prop,
- "Attraction Strength",
- "Force strength for directional attraction towards the control object");
-
- prop = RNA_def_property(srna, "attraction_radius", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "attractforceRadius");
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(
- prop, "Attraction Radius", "Force field radius around the control object");
-
- prop = RNA_def_property(srna, "velocity_strength", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "velocityforceStrength");
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(
- prop,
- "Velocity Strength",
- "Force strength of how much of the control object's velocity is influencing the "
- "fluid velocity");
-
- prop = RNA_def_property(srna, "velocity_radius", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "velocityforceRadius");
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(
- prop, "Velocity Radius", "Force field radius around the control object");
-
- prop = RNA_def_property(srna, "quality", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "cpsQuality");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 5.0, 100.0);
- RNA_def_property_ui_text(
- prop, "Quality", "Quality which is used for object sampling (higher = better but slower)");
-
- prop = RNA_def_property(srna, "use_reverse_frames", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", OB_FLUIDSIM_REVERSE);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Reverse Frames", "Reverse control object movement");
- RNA_def_property_update(prop, 0, "rna_fluid_find_enframe");
-}
-
-void RNA_def_fluidsim(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static const EnumPropertyItem prop_fluid_type_items[] = {
- {OB_FLUIDSIM_ENABLE, "NONE", 0, "None", ""},
- {OB_FLUIDSIM_DOMAIN,
- "DOMAIN",
- 0,
- "Domain",
- "Bounding box of this object represents the computational domain of the "
- "fluid simulation"},
- {OB_FLUIDSIM_FLUID,
- "FLUID",
- 0,
- "Fluid",
- "Object represents a volume of fluid in the simulation"},
- {OB_FLUIDSIM_OBSTACLE, "OBSTACLE", 0, "Obstacle", "Object is a fixed obstacle"},
- {OB_FLUIDSIM_INFLOW, "INFLOW", 0, "Inflow", "Object adds fluid to the simulation"},
- {OB_FLUIDSIM_OUTFLOW, "OUTFLOW", 0, "Outflow", "Object removes fluid from the simulation"},
- {OB_FLUIDSIM_PARTICLE,
- "PARTICLE",
- 0,
- "Particle",
- "Object is made a particle system to display particles generated by a "
- "fluidsim domain object"},
- {OB_FLUIDSIM_CONTROL,
- "CONTROL",
- 0,
- "Control",
- "Object is made a fluid control mesh, which influences the fluid"},
- {0, NULL, 0, NULL, NULL},
- };
-
- srna = RNA_def_struct(brna, "FluidSettings", NULL);
- RNA_def_struct_sdna(srna, "FluidsimSettings");
- RNA_def_struct_refine_func(srna, "rna_FluidSettings_refine");
- RNA_def_struct_path_func(srna, "rna_FluidSettings_path");
- RNA_def_struct_ui_text(srna,
- "Fluid Simulation Settings",
- "Fluid simulation settings for an object taking part in the simulation");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, prop_fluid_type_items);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Type", "Type of participation in the fluid simulation");
- RNA_def_property_update(prop, 0, "rna_FluidSettings_update_type");
-
-# if 0
- prop = RNA_def_property(srna, "ipo", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "IPO Curves", "IPO curves used by fluid simulation settings");
-# endif
-
- /* types */
-
- rna_def_fluidsim_domain(brna);
- rna_def_fluidsim_fluid(brna);
- rna_def_fluidsim_obstacle(brna);
- rna_def_fluidsim_inflow(brna);
- rna_def_fluidsim_outflow(brna);
- rna_def_fluidsim_particle(brna);
- rna_def_fluidsim_control(brna);
-}
-
-#endif
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 7aa3ee60c5a..2f59cde7e94 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -43,7 +43,7 @@
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
-#include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */
+#include "BKE_fluid.h" /* For BKE_fluid_modifier_free & BKE_fluid_modifier_create_type_data */
#include "RNA_access.h"
#include "RNA_define.h"
@@ -174,7 +174,7 @@ static const EnumPropertyItem rna_enum_time_mode_items[] = {
# include "DNA_particle_types.h"
# include "DNA_curve_types.h"
-# include "DNA_smoke_types.h"
+# include "DNA_fluid_types.h"
# include "BKE_cachefile.h"
# include "BKE_context.h"
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 7a03bdb952b..d07bf542954 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -317,8 +317,9 @@ static void rna_Image_active_tile_set(PointerRNA *ptr,
Image *image = (Image *)ptr->data;
ImageTile *tile = (ImageTile *)value.data;
const int index = BLI_findindex(&image->tiles, tile);
- if (index != -1)
+ if (index != -1) {
image->active_tile_index = index;
+ }
}
static bool rna_Image_has_data_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 94394a4826b..46455a43b2e 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -155,7 +155,6 @@ void RNA_def_controller(struct BlenderRNA *brna);
void RNA_def_curve(struct BlenderRNA *brna);
void RNA_def_depsgraph(struct BlenderRNA *brna);
void RNA_def_dynamic_paint(struct BlenderRNA *brna);
-void RNA_def_fluidsim(struct BlenderRNA *brna);
void RNA_def_fcurve(struct BlenderRNA *brna);
void RNA_def_gpencil(struct BlenderRNA *brna);
void RNA_def_greasepencil_modifier(struct BlenderRNA *brna);
@@ -188,7 +187,7 @@ void RNA_def_view_layer(struct BlenderRNA *brna);
void RNA_def_screen(struct BlenderRNA *brna);
void RNA_def_sculpt_paint(struct BlenderRNA *brna);
void RNA_def_sequencer(struct BlenderRNA *brna);
-void RNA_def_smoke(struct BlenderRNA *brna);
+void RNA_def_fluid(struct BlenderRNA *brna);
void RNA_def_space(struct BlenderRNA *brna);
void RNA_def_speaker(struct BlenderRNA *brna);
void RNA_def_test(struct BlenderRNA *brna);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 7c9ac6a2072..1896c9dbec3 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -45,7 +45,7 @@
#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
#include "BKE_ocean.h"
-#include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */
+#include "BKE_fluid.h" /* For BKE_fluid_modifier_free & BKE_fluid_modifier_create_type_data */
#include "RNA_access.h"
#include "RNA_define.h"
@@ -277,7 +277,6 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
ICON_MOD_EXPLODE,
"Explode",
"Break apart the mesh faces and let them follow particles"},
- {eModifierType_Fluidsim, "FLUID_SIMULATION", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""},
{eModifierType_Ocean, "OCEAN", ICON_MOD_OCEAN, "Ocean", "Generate a moving ocean surface"},
{eModifierType_ParticleInstance,
"PARTICLE_INSTANCE",
@@ -289,7 +288,7 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
ICON_MOD_PARTICLES,
"Particle System",
"Spawn particles from the shape"},
- {eModifierType_Smoke, "SMOKE", ICON_MOD_SMOKE, "Smoke", ""},
+ {eModifierType_Fluid, "FLUID", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""},
{eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""},
{eModifierType_Surface, "SURFACE", ICON_MODIFIER, "Surface", ""},
{eModifierType_BParticles, "BPARTICLES", ICON_NONE, "BParticles", ""},
@@ -584,7 +583,7 @@ const EnumPropertyItem rna_enum_axis_flag_xyz_items[] = {
#ifdef RNA_RUNTIME
# include "DNA_particle_types.h"
# include "DNA_curve_types.h"
-# include "DNA_smoke_types.h"
+# include "DNA_fluid_types.h"
# include "BKE_cachefile.h"
# include "BKE_context.h"
@@ -665,8 +664,6 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_BevelModifier;
case eModifierType_Shrinkwrap:
return &RNA_ShrinkwrapModifier;
- case eModifierType_Fluidsim:
- return &RNA_FluidSimulationModifier;
case eModifierType_Mask:
return &RNA_MaskModifier;
case eModifierType_SimpleDeform:
@@ -675,8 +672,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_MultiresModifier;
case eModifierType_Surface:
return &RNA_SurfaceModifier;
- case eModifierType_Smoke:
- return &RNA_SmokeModifier;
+ case eModifierType_Fluid:
+ return &RNA_FluidModifier;
case eModifierType_Solidify:
return &RNA_SolidifyModifier;
case eModifierType_Screw:
@@ -732,6 +729,7 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
case eModifierType_BParticlesOutput:
return &RNA_BParticlesOutputModifier;
/* Default */
+ case eModifierType_Fluidsim: /* deprecated */
case eModifierType_None:
case eModifierType_ShapeKey:
case NUM_MODIFIER_TYPES:
@@ -1041,25 +1039,27 @@ static void rna_UVProjector_object_set(PointerRNA *ptr,
/* Other rna callbacks */
-static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_fluid_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- SmokeModifierData *smd = (SmokeModifierData *)ptr->data;
+ FluidModifierData *mmd = (FluidModifierData *)ptr->data;
Object *ob = (Object *)ptr->owner_id;
/* nothing changed */
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
+ if ((mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
return;
}
- smokeModifier_free(smd); /* XXX TODO: completely free all 3 pointers */
- smokeModifier_createType(smd); /* create regarding of selected type */
+# ifdef WITH_FLUID
+ BKE_fluid_modifier_free(mmd); /* XXX TODO: completely free all 3 pointers */
+ BKE_fluid_modifier_create_type_data(mmd); /* create regarding of selected type */
+# endif
- switch (smd->type) {
- case MOD_SMOKE_TYPE_DOMAIN:
+ switch (mmd->type) {
+ case MOD_FLUID_TYPE_DOMAIN:
ob->dt = OB_WIRE;
break;
- case MOD_SMOKE_TYPE_FLOW:
- case MOD_SMOKE_TYPE_COLL:
+ case MOD_FLUID_TYPE_FLOW:
+ case MOD_FLUID_TYPE_EFFEC:
case 0:
default:
break;
@@ -3619,23 +3619,23 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Hair Grid Resolution", "");
}
-static void rna_def_modifier_smoke(BlenderRNA *brna)
+static void rna_def_modifier_fluid(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- static const EnumPropertyItem prop_smoke_type_items[] = {
+ static const EnumPropertyItem prop_fluid_type_items[] = {
{0, "NONE", 0, "None", ""},
- {MOD_SMOKE_TYPE_DOMAIN, "DOMAIN", 0, "Domain", ""},
- {MOD_SMOKE_TYPE_FLOW, "FLOW", 0, "Flow", "Inflow/Outflow"},
- {MOD_SMOKE_TYPE_COLL, "COLLISION", 0, "Collision", ""},
+ {MOD_FLUID_TYPE_DOMAIN, "DOMAIN", 0, "Domain", ""},
+ {MOD_FLUID_TYPE_FLOW, "FLOW", 0, "Flow", "Inflow/Outflow"},
+ {MOD_FLUID_TYPE_EFFEC, "EFFECTOR", 0, "Effector", ""},
{0, NULL, 0, NULL, NULL},
};
- srna = RNA_def_struct(brna, "SmokeModifier", "Modifier");
- RNA_def_struct_ui_text(srna, "Smoke Modifier", "Smoke simulation modifier");
- RNA_def_struct_sdna(srna, "SmokeModifierData");
- RNA_def_struct_ui_icon(srna, ICON_MOD_SMOKE);
+ srna = RNA_def_struct(brna, "FluidModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Fluid Modifier", "Fluid simulation modifier");
+ RNA_def_struct_sdna(srna, "FluidModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_FLUIDSIM);
prop = RNA_def_property(srna, "domain_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "domain");
@@ -3645,16 +3645,16 @@ static void rna_def_modifier_smoke(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "flow");
RNA_def_property_ui_text(prop, "Flow Settings", "");
- prop = RNA_def_property(srna, "coll_settings", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "coll");
- RNA_def_property_ui_text(prop, "Collision Settings", "");
+ prop = RNA_def_property(srna, "effector_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "effector");
+ RNA_def_property_ui_text(prop, "Effector Settings", "");
- prop = RNA_def_property(srna, "smoke_type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "fluid_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, prop_smoke_type_items);
+ RNA_def_property_enum_items(prop, prop_fluid_type_items);
RNA_def_property_ui_text(prop, "Type", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, 0, "rna_Smoke_set_type");
+ RNA_def_property_update(prop, 0, "rna_fluid_set_type");
}
static void rna_def_modifier_dynamic_paint(BlenderRNA *brna)
@@ -4081,23 +4081,6 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
-static void rna_def_modifier_fluidsim(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "FluidSimulationModifier", "Modifier");
- RNA_def_struct_ui_text(srna, "Fluid Simulation Modifier", "Fluid simulation modifier");
- RNA_def_struct_sdna(srna, "FluidsimModifierData");
- RNA_def_struct_ui_icon(srna, ICON_MOD_FLUIDSIM);
-
- prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "fss");
- RNA_def_property_ui_text(
- prop, "Settings", "Settings for how this object is used in the fluid simulation");
-}
-
static void rna_def_modifier_mask(BlenderRNA *brna)
{
StructRNA *srna;
@@ -6508,13 +6491,12 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_collision(brna);
rna_def_modifier_bevel(brna);
rna_def_modifier_shrinkwrap(brna);
- rna_def_modifier_fluidsim(brna);
rna_def_modifier_mask(brna);
rna_def_modifier_simpledeform(brna);
rna_def_modifier_warp(brna);
rna_def_modifier_multires(brna);
rna_def_modifier_surface(brna);
- rna_def_modifier_smoke(brna);
+ rna_def_modifier_fluid(brna);
rna_def_modifier_solidify(brna);
rna_def_modifier_screw(brna);
rna_def_modifier_uvwarp(brna);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 17e34cd60ad..68e3e522dff 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -4506,7 +4506,7 @@ static void def_sh_tex_voronoi(StructRNA *srna)
"SMOOTH_F1",
0,
"Smooth F1",
- "Smoothed version of F1. Weighted sum of neighbour voronoi cells"},
+ "Smoothed version of F1. Weighted sum of neighbor voronoi cells"},
{SHD_VORONOI_DISTANCE_TO_EDGE,
"DISTANCE_TO_EDGE",
0,
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 16d70e21ec2..559b8ca4cc1 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -25,7 +25,7 @@
#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -738,10 +738,10 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr)
}
/* check smoke modifier */
- md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+ md = (ModifierData *)modifiers_findByType(ob, eModifierType_Fluid);
if (md) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->domain->effector_weights == ew) {
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ if (mmd->domain->effector_weights == ew) {
char name_esc[sizeof(md->name) * 2];
BLI_strescape(name_esc, md->name, sizeof(name_esc));
return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc);
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 211d9e19ab4..51df843947d 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -950,11 +950,12 @@ static float rna_PartSetting_linelenhead_get(struct PointerRNA *ptr)
return settings->draw_line[1];
}
-static bool rna_PartSettings_is_fluid_get(PointerRNA *ptr)
+static int rna_PartSettings_is_fluid_get(PointerRNA *ptr)
{
ParticleSettings *part = (ParticleSettings *)ptr->data;
- return part->type == PART_FLUID;
+ return (part->type & (PART_FLUID_FLIP | PART_FLUID_SPRAY | PART_FLUID_BUBBLE | PART_FLUID_FOAM |
+ PART_FLUID_TRACER));
}
static void rna_ParticleSettings_use_clump_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
deleted file mode 100644
index c00cc789eff..00000000000
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ /dev/null
@@ -1,1218 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/** \file
- * \ingroup RNA
- */
-
-#include <stdlib.h>
-#include <limits.h>
-
-#include "BLI_sys_types.h"
-
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
-#include "BKE_modifier.h"
-#include "BKE_smoke.h"
-#include "BKE_pointcache.h"
-
-#include "DNA_modifier_types.h"
-#include "DNA_object_force_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_smoke_types.h"
-
-#include "WM_types.h"
-
-#ifdef RNA_RUNTIME
-
-# include "BLI_threads.h"
-
-# include "BKE_colorband.h"
-# include "BKE_context.h"
-# include "BKE_particle.h"
-
-# include "DEG_depsgraph.h"
-# include "DEG_depsgraph_build.h"
-
-# include "smoke_API.h"
-
-static void rna_Smoke_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
-}
-
-static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- rna_Smoke_update(bmain, scene, ptr);
- DEG_relations_tag_update(bmain);
-}
-
-static void rna_Smoke_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
- if (settings->smd && settings->smd->domain) {
- settings->point_cache[0]->flag |= PTCACHE_OUTDATED;
- }
- DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
-}
-
-static void rna_Smoke_cachetype_set(struct PointerRNA *ptr, int value)
-{
- SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
- Object *ob = (Object *)ptr->owner_id;
-
- if (value != settings->cache_file_format) {
- /* Clear old caches. */
- PTCacheID id;
- BKE_ptcache_id_from_smoke(&id, ob, settings->smd);
- BKE_ptcache_id_clear(&id, PTCACHE_CLEAR_ALL, 0);
-
- settings->cache_file_format = value;
- }
-}
-
-static void rna_Smoke_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
-
- smokeModifier_reset(settings->smd);
- rna_Smoke_resetCache(bmain, scene, ptr);
-
- rna_Smoke_update(bmain, scene, ptr);
-}
-
-static void rna_Smoke_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
-
- smokeModifier_reset(settings->smd);
-
- if (settings->smd && settings->smd->domain) {
- settings->smd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED;
- }
-
- rna_Smoke_dependency_update(bmain, scene, ptr);
-}
-
-static char *rna_SmokeDomainSettings_path(PointerRNA *ptr)
-{
- SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
- ModifierData *md = (ModifierData *)settings->smd;
- char name_esc[sizeof(md->name) * 2];
-
- BLI_strescape(name_esc, md->name, sizeof(name_esc));
- return BLI_sprintfN("modifiers[\"%s\"].domain_settings", name_esc);
-}
-
-static char *rna_SmokeFlowSettings_path(PointerRNA *ptr)
-{
- SmokeFlowSettings *settings = (SmokeFlowSettings *)ptr->data;
- ModifierData *md = (ModifierData *)settings->smd;
- char name_esc[sizeof(md->name) * 2];
-
- BLI_strescape(name_esc, md->name, sizeof(name_esc));
- return BLI_sprintfN("modifiers[\"%s\"].flow_settings", name_esc);
-}
-
-static char *rna_SmokeCollSettings_path(PointerRNA *ptr)
-{
- SmokeCollSettings *settings = (SmokeCollSettings *)ptr->data;
- ModifierData *md = (ModifierData *)settings->smd;
- char name_esc[sizeof(md->name) * 2];
-
- BLI_strescape(name_esc, md->name, sizeof(name_esc));
- return BLI_sprintfN("modifiers[\"%s\"].coll_settings", name_esc);
-}
-
-static int rna_SmokeModifier_grid_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- float *density = NULL;
- int size = 0;
-
- if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
- /* high resolution smoke */
- int res[3];
-
- smoke_turbulence_get_res(sds->wt, res);
- size = res[0] * res[1] * res[2];
-
- density = smoke_turbulence_get_density(sds->wt);
- }
- else if (sds->fluid) {
- /* regular resolution */
- size = sds->res[0] * sds->res[1] * sds->res[2];
- density = smoke_get_density(sds->fluid);
- }
-
- length[0] = (density) ? size : 0;
-# else
- (void)ptr;
- length[0] = 0;
-# endif
- return length[0];
-}
-
-static int rna_SmokeModifier_color_grid_get_length(PointerRNA *ptr,
- int length[RNA_MAX_ARRAY_DIMENSION])
-{
- rna_SmokeModifier_grid_get_length(ptr, length);
-
- length[0] *= 4;
- return length[0];
-}
-
-static int rna_SmokeModifier_velocity_grid_get_length(PointerRNA *ptr,
- int length[RNA_MAX_ARRAY_DIMENSION])
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- float *vx = NULL;
- float *vy = NULL;
- float *vz = NULL;
- int size = 0;
-
- /* Velocity data is always low-resolution. */
- if (sds->fluid) {
- size = 3 * sds->res[0] * sds->res[1] * sds->res[2];
- vx = smoke_get_velocity_x(sds->fluid);
- vy = smoke_get_velocity_y(sds->fluid);
- vz = smoke_get_velocity_z(sds->fluid);
- }
-
- length[0] = (vx && vy && vz) ? size : 0;
-# else
- (void)ptr;
- length[0] = 0;
-# endif
- return length[0];
-}
-
-static int rna_SmokeModifier_heat_grid_get_length(PointerRNA *ptr,
- int length[RNA_MAX_ARRAY_DIMENSION])
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- float *heat = NULL;
- int size = 0;
-
- /* Heat data is always low-resolution. */
- if (sds->fluid) {
- size = sds->res[0] * sds->res[1] * sds->res[2];
- heat = smoke_get_heat(sds->fluid);
- }
-
- length[0] = (heat) ? size : 0;
-# else
- (void)ptr;
- length[0] = 0;
-# endif
- return length[0];
-}
-
-static void rna_SmokeModifier_density_grid_get(PointerRNA *ptr, float *values)
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- int length[RNA_MAX_ARRAY_DIMENSION];
- int size = rna_SmokeModifier_grid_get_length(ptr, length);
- float *density;
-
- BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
-
- if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
- density = smoke_turbulence_get_density(sds->wt);
- }
- else {
- density = smoke_get_density(sds->fluid);
- }
-
- memcpy(values, density, size * sizeof(float));
-
- BLI_rw_mutex_unlock(sds->fluid_mutex);
-# else
- UNUSED_VARS(ptr, values);
-# endif
-}
-
-static void rna_SmokeModifier_velocity_grid_get(PointerRNA *ptr, float *values)
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- int length[RNA_MAX_ARRAY_DIMENSION];
- int size = rna_SmokeModifier_velocity_grid_get_length(ptr, length);
- float *vx, *vy, *vz;
- int i;
-
- BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
-
- vx = smoke_get_velocity_x(sds->fluid);
- vy = smoke_get_velocity_y(sds->fluid);
- vz = smoke_get_velocity_z(sds->fluid);
-
- for (i = 0; i < size; i += 3) {
- *(values++) = *(vx++);
- *(values++) = *(vy++);
- *(values++) = *(vz++);
- }
-
- BLI_rw_mutex_unlock(sds->fluid_mutex);
-# else
- UNUSED_VARS(ptr, values);
-# endif
-}
-
-static void rna_SmokeModifier_color_grid_get(PointerRNA *ptr, float *values)
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- int length[RNA_MAX_ARRAY_DIMENSION];
- int size = rna_SmokeModifier_grid_get_length(ptr, length);
-
- BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
-
- if (!sds->fluid) {
- memset(values, 0, size * sizeof(float));
- }
- else {
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- if (smoke_turbulence_has_colors(sds->wt)) {
- smoke_turbulence_get_rgba(sds->wt, values, 0);
- }
- else {
- smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, values, 0);
- }
- }
- else {
- if (smoke_has_colors(sds->fluid)) {
- smoke_get_rgba(sds->fluid, values, 0);
- }
- else {
- smoke_get_rgba_from_density(sds->fluid, sds->active_color, values, 0);
- }
- }
- }
-
- BLI_rw_mutex_unlock(sds->fluid_mutex);
-# else
- UNUSED_VARS(ptr, values);
-# endif
-}
-
-static void rna_SmokeModifier_flame_grid_get(PointerRNA *ptr, float *values)
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- int length[RNA_MAX_ARRAY_DIMENSION];
- int size = rna_SmokeModifier_grid_get_length(ptr, length);
- float *flame;
-
- BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
-
- if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
- flame = smoke_turbulence_get_flame(sds->wt);
- }
- else {
- flame = smoke_get_flame(sds->fluid);
- }
-
- if (flame) {
- memcpy(values, flame, size * sizeof(float));
- }
- else {
- memset(values, 0, size * sizeof(float));
- }
-
- BLI_rw_mutex_unlock(sds->fluid_mutex);
-# else
- UNUSED_VARS(ptr, values);
-# endif
-}
-
-static void rna_SmokeModifier_heat_grid_get(PointerRNA *ptr, float *values)
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- int length[RNA_MAX_ARRAY_DIMENSION];
- int size = rna_SmokeModifier_heat_grid_get_length(ptr, length);
- float *heat;
-
- BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
-
- heat = smoke_get_heat(sds->fluid);
-
- if (heat != NULL) {
- /* scale heat values from -2.0-2.0 to -1.0-1.0. */
- for (int i = 0; i < size; i++) {
- values[i] = heat[i] * 0.5f;
- }
- }
- else {
- memset(values, 0, size * sizeof(float));
- }
-
- BLI_rw_mutex_unlock(sds->fluid_mutex);
-# else
- UNUSED_VARS(ptr, values);
-# endif
-}
-
-static void rna_SmokeModifier_temperature_grid_get(PointerRNA *ptr, float *values)
-{
-# ifdef WITH_SMOKE
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
- int length[RNA_MAX_ARRAY_DIMENSION];
- int size = rna_SmokeModifier_grid_get_length(ptr, length);
- float *flame;
-
- BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
-
- if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
- flame = smoke_turbulence_get_flame(sds->wt);
- }
- else {
- flame = smoke_get_flame(sds->fluid);
- }
-
- if (flame) {
- /* Output is such that 0..1 maps to 0..1000K */
- float offset = sds->flame_ignition;
- float scale = sds->flame_max_temp - sds->flame_ignition;
-
- for (int i = 0; i < size; i++) {
- values[i] = (flame[i] > 0.01f) ? offset + flame[i] * scale : 0.0f;
- }
- }
- else {
- memset(values, 0, size * sizeof(float));
- }
-
- BLI_rw_mutex_unlock(sds->fluid_mutex);
-# else
- UNUSED_VARS(ptr, values);
-# endif
-}
-
-static void rna_SmokeFlow_density_vgroup_get(PointerRNA *ptr, char *value)
-{
- SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
- rna_object_vgroup_name_index_get(ptr, value, flow->vgroup_density);
-}
-
-static int rna_SmokeFlow_density_vgroup_length(PointerRNA *ptr)
-{
- SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
- return rna_object_vgroup_name_index_length(ptr, flow->vgroup_density);
-}
-
-static void rna_SmokeFlow_density_vgroup_set(PointerRNA *ptr, const char *value)
-{
- SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
- rna_object_vgroup_name_index_set(ptr, value, &flow->vgroup_density);
-}
-
-static void rna_SmokeFlow_uvlayer_set(PointerRNA *ptr, const char *value)
-{
- SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
- rna_object_uvlayer_name_set(ptr, value, flow->uvlayer_name, sizeof(flow->uvlayer_name));
-}
-
-static void rna_Smoke_use_color_ramp_set(PointerRNA *ptr, bool value)
-{
- SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
-
- sds->use_coba = value;
-
- if (value && sds->coba == NULL) {
- sds->coba = BKE_colorband_add(false);
- }
-}
-
-#else
-
-static void rna_def_smoke_domain_settings(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static const EnumPropertyItem prop_noise_type_items[] = {
- {MOD_SMOKE_NOISEWAVE, "NOISEWAVE", 0, "Wavelet", ""},
-# ifdef WITH_FFTW3
- {MOD_SMOKE_NOISEFFT, "NOISEFFT", 0, "FFT", ""},
-# endif
- /* {MOD_SMOKE_NOISECURL, "NOISECURL", 0, "Curl", ""}, */
- {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
- {VDB_COMPRESSION_BLOSC,
- "BLOSC",
- 0,
- "Blosc",
- "Multithreaded compression, similar in size and quality as 'Zip'"},
-# endif
- {VDB_COMPRESSION_NONE, "NONE", 0, "None", "Do not use any compression"},
- {0, NULL, 0, NULL, NULL}};
-
- static const EnumPropertyItem smoke_cache_comp_items[] = {
- {SM_CACHE_LIGHT, "CACHELIGHT", 0, "Lite", "Fast but not so effective compression"},
- {SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem smoke_highres_sampling_items[] = {
- {SM_HRES_FULLSAMPLE, "FULLSAMPLE", 0, "Full Sample", ""},
- {SM_HRES_LINEAR, "LINEAR", 0, "Linear", ""},
- {SM_HRES_NEAREST, "NEAREST", 0, "Nearest", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem smoke_data_depth_items[] = {
- {16, "16", 0, "Float (Half)", "Half float (16 bit data)"},
- {0, "32", 0, "Float (Full)", "Full float (32 bit data)"}, /* default */
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem smoke_domain_colli_items[] = {
- {SM_BORDER_OPEN, "BORDEROPEN", 0, "Open", "Smoke doesn't collide with any border"},
- {SM_BORDER_VERTICAL,
- "BORDERVERTICAL",
- 0,
- "Vertically Open",
- "Smoke doesn't collide with top and bottom sides"},
- {SM_BORDER_CLOSED, "BORDERCLOSED", 0, "Collide All", "Smoke collides with every side"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem cache_file_type_items[] = {
- {PTCACHE_FILE_PTCACHE,
- "POINTCACHE",
- 0,
- "Point Cache",
- "Blender specific point cache file format"},
-# ifdef WITH_OPENVDB
- {PTCACHE_FILE_OPENVDB, "OPENVDB", 0, "OpenVDB", "OpenVDB file format"},
-# endif
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem smoke_view_items[] = {
- {MOD_SMOKE_SLICE_VIEW_ALIGNED,
- "VIEW_ALIGNED",
- 0,
- "View",
- "Slice volume parallel to the view plane"},
- {MOD_SMOKE_SLICE_AXIS_ALIGNED,
- "AXIS_ALIGNED",
- 0,
- "Axis",
- "Slice volume parallel to the major axis"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem axis_slice_method_items[] = {
- {AXIS_SLICE_FULL, "FULL", 0, "Full", "Slice the whole domain object"},
- {AXIS_SLICE_SINGLE, "SINGLE", 0, "Single", "Perform a single slice of the domain object"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem interp_method_item[] = {
- {VOLUME_INTERP_LINEAR, "LINEAR", 0, "Linear", "Good smoothness and speed"},
- {VOLUME_INTERP_CUBIC,
- "CUBIC",
- 0,
- "Cubic",
- "Smoothed high quality interpolation, but slower"},
- {0, NULL, 0, NULL, NULL},
- };
-
- 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, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem vector_draw_items[] = {
- {VECTOR_DRAW_NEEDLE, "NEEDLE", 0, "Needle", "Display vectors as needles"},
- {VECTOR_DRAW_STREAMLINE, "STREAMLINE", 0, "Streamlines", "Display vectors as streamlines"},
- {0, NULL, 0, NULL, NULL},
- };
-
- srna = RNA_def_struct(brna, "SmokeDomainSettings", NULL);
- RNA_def_struct_ui_text(srna, "Domain Settings", "Smoke domain settings");
- RNA_def_struct_sdna(srna, "SmokeDomainSettings");
- RNA_def_struct_path_func(srna, "rna_SmokeDomainSettings_path");
-
- prop = RNA_def_property(srna, "resolution_max", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "maxres");
- RNA_def_property_range(prop, 6, 512);
- RNA_def_property_ui_range(prop, 24, 512, 2, -1);
- RNA_def_property_ui_text(prop, "Max Res", "Maximal resolution used in the fluid domain");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "amplify", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "amplify");
- RNA_def_property_range(prop, 1, 10);
- RNA_def_property_ui_range(prop, 1, 10, 1, -1);
- RNA_def_property_ui_text(
- prop, "Amplification", "Enhance the resolution of smoke by this factor using noise");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "use_high_resolution", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGHRES);
- RNA_def_property_ui_text(prop, "High Res", "Enable high resolution (using amplification)");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "show_high_resolution", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "viewsettings", MOD_SMOKE_VIEW_SHOW_HIGHRES);
- RNA_def_property_ui_text(
- prop, "Show High Resolution", "Show high resolution (using amplification)");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "noise");
- RNA_def_property_enum_items(prop, prop_noise_type_items);
- RNA_def_property_ui_text(
- prop, "Noise Method", "Noise method which is used for creating the high resolution");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "alpha");
- RNA_def_property_range(prop, -5.0, 5.0);
- RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
- RNA_def_property_ui_text(
- prop,
- "Density",
- "How much density affects smoke motion (higher value results in faster rising smoke)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "beta");
- RNA_def_property_range(prop, -5.0, 5.0);
- RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
- RNA_def_property_ui_text(
- prop,
- "Heat",
- "How much heat affects smoke motion (higher value results in faster rising smoke)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "collision_collection", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "coll_group");
- RNA_def_property_struct_type(prop, "Collection");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Collision Collection", "Limit collisions to this collection");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset_dependency");
-
- prop = RNA_def_property(srna, "fluid_collection", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "fluid_group");
- RNA_def_property_struct_type(prop, "Collection");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Fluid Collection", "Limit fluid objects to this collection");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset_dependency");
-
- prop = RNA_def_property(srna, "effector_collection", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "eff_group");
- RNA_def_property_struct_type(prop, "Collection");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Effector Collection", "Limit effectors to this collection");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset_dependency");
-
- prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "strength");
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 2);
- RNA_def_property_ui_text(prop, "Strength", "Strength of noise");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_TIME);
- RNA_def_property_int_sdna(prop, NULL, "diss_speed");
- RNA_def_property_range(prop, 1.0, 10000.0);
- RNA_def_property_ui_range(prop, 1.0, 10000.0, 1, -1);
- RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "use_dissolve_smoke", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE);
- RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "use_dissolve_smoke_log", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE_LOG);
- RNA_def_property_ui_text(prop, "Logarithmic Dissolve", "Using 1/x ");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "point_cache[0]");
- RNA_def_property_struct_type(prop, "PointCache");
- RNA_def_property_ui_text(prop, "Point Cache", "");
-
- prop = RNA_def_property(srna, "point_cache_compress_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "cache_comp");
- RNA_def_property_enum_items(prop, smoke_cache_comp_items);
- RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
-
- prop = RNA_def_property(srna, "openvdb_cache_compress_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "openvdb_comp");
- RNA_def_property_enum_items(prop, prop_compression_items);
- RNA_def_property_ui_text(prop, "Compression", "Compression method to be used");
-
- prop = RNA_def_property(srna, "data_depth", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "data_depth");
- RNA_def_property_enum_items(prop, smoke_data_depth_items);
- RNA_def_property_ui_text(prop,
- "Data Depth",
- "Bit depth for writing all scalar (including vector) "
- "lower values reduce file size");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
-
- prop = RNA_def_property(srna, "collision_extents", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "border_collisions");
- RNA_def_property_enum_items(prop, smoke_domain_colli_items);
- RNA_def_property_ui_text(
- prop, "Border Collisions", "Select which domain border will be treated as collision object");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "EffectorWeights");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Effector Weights", "");
-
- prop = RNA_def_property(srna, "highres_sampling", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, smoke_highres_sampling_items);
- RNA_def_property_ui_text(prop, "Emitter", "Method for sampling the high resolution flow");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- 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.2, 1.5);
- RNA_def_property_ui_range(prop, 0.2, 1.5, 0.02, 5);
- RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "vorticity");
- RNA_def_property_range(prop, 0.01, 4.0);
- RNA_def_property_ui_range(prop, 0.01, 4.0, 0.02, 5);
- RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence/rotation in fluid");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "density_grid", PROP_FLOAT, PROP_NONE);
- RNA_def_property_array(prop, 32);
- RNA_def_property_flag(prop, PROP_DYNAMIC);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_grid_get_length");
- RNA_def_property_float_funcs(prop, "rna_SmokeModifier_density_grid_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Density Grid", "Smoke density grid");
-
- prop = RNA_def_property(srna, "velocity_grid", PROP_FLOAT, PROP_NONE);
- RNA_def_property_array(prop, 32);
- RNA_def_property_flag(prop, PROP_DYNAMIC);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_velocity_grid_get_length");
- RNA_def_property_float_funcs(prop, "rna_SmokeModifier_velocity_grid_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Velocity Grid", "Smoke velocity grid");
-
- prop = RNA_def_property(srna, "flame_grid", PROP_FLOAT, PROP_NONE);
- RNA_def_property_array(prop, 32);
- RNA_def_property_flag(prop, PROP_DYNAMIC);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_grid_get_length");
- RNA_def_property_float_funcs(prop, "rna_SmokeModifier_flame_grid_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Flame Grid", "Smoke flame grid");
-
- prop = RNA_def_property(srna, "color_grid", PROP_FLOAT, PROP_NONE);
- RNA_def_property_array(prop, 32);
- RNA_def_property_flag(prop, PROP_DYNAMIC);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_color_grid_get_length");
- RNA_def_property_float_funcs(prop, "rna_SmokeModifier_color_grid_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Color Grid", "Smoke color grid");
-
- prop = RNA_def_property(srna, "heat_grid", PROP_FLOAT, PROP_NONE);
- RNA_def_property_array(prop, 32);
- RNA_def_property_flag(prop, PROP_DYNAMIC);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_heat_grid_get_length");
- RNA_def_property_float_funcs(prop, "rna_SmokeModifier_heat_grid_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Heat Grid", "Smoke heat grid");
-
- prop = RNA_def_property(srna, "temperature_grid", PROP_FLOAT, PROP_NONE);
- RNA_def_property_array(prop, 32);
- RNA_def_property_flag(prop, PROP_DYNAMIC);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_grid_get_length");
- RNA_def_property_float_funcs(prop, "rna_SmokeModifier_temperature_grid_get", NULL, NULL);
- RNA_def_property_ui_text(
- prop, "Temperature Grid", "Smoke temperature grid, range 0..1 represents 0..1000K");
-
- prop = RNA_def_property(srna,
- "cell_size",
- PROP_FLOAT,
- PROP_XYZ); /* can change each frame when using adaptive domain */
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "cell_size", "Cell Size");
-
- prop = RNA_def_property(srna,
- "start_point",
- PROP_FLOAT,
- PROP_XYZ); /* can change each frame when using adaptive domain */
- RNA_def_property_float_sdna(prop, NULL, "p0");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "p0", "Start point");
-
- prop = RNA_def_property(srna,
- "domain_resolution",
- PROP_INT,
- PROP_XYZ); /* can change each frame when using adaptive domain */
- RNA_def_property_int_sdna(prop, NULL, "res");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "res", "Smoke Grid Resolution");
-
- prop = RNA_def_property(srna, "burning_rate", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.01, 4.0);
- RNA_def_property_ui_range(prop, 0.01, 2.0, 1.0, 5);
- RNA_def_property_ui_text(
- prop, "Speed", "Speed of the burning reaction (use larger values for smaller flame)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "flame_smoke", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 8.0);
- RNA_def_property_ui_range(prop, 0.0, 4.0, 1.0, 5);
- RNA_def_property_ui_text(prop, "Smoke", "Amount of smoke created by burning fuel");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "flame_vorticity", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_range(prop, 0.0, 2.0);
- RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 5);
- RNA_def_property_ui_text(prop, "Vorticity", "Additional vorticity for the flames");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "flame_ignition", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.5, 5.0);
- RNA_def_property_ui_range(prop, 0.5, 2.5, 1.0, 5);
- RNA_def_property_ui_text(prop, "Ignition", "Minimum temperature of flames");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "flame_max_temp", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 1.0, 10.0);
- RNA_def_property_ui_range(prop, 1.0, 5.0, 1.0, 5);
- RNA_def_property_ui_text(prop, "Maximum", "Maximum temperature of flames");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "flame_smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke emitted from burning fuel");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "use_adaptive_domain", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_ADAPTIVE_DOMAIN);
- RNA_def_property_ui_text(
- prop, "Adaptive Domain", "Adapt simulation resolution and size to fluid");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "additional_res", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "adapt_res");
- RNA_def_property_range(prop, 0, 512);
- RNA_def_property_ui_range(prop, 0, 512, 2, -1);
- RNA_def_property_ui_text(prop, "Additional", "Maximum number of additional cells");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "adapt_margin", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "adapt_margin");
- RNA_def_property_range(prop, 2, 24);
- RNA_def_property_ui_range(prop, 2, 24, 2, -1);
- RNA_def_property_ui_text(
- prop, "Margin", "Margin added around fluid to minimize boundary interference");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "adapt_threshold", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.01, 0.5);
- RNA_def_property_ui_range(prop, 0.01, 0.5, 1.0, 5);
- RNA_def_property_ui_text(
- prop, "Threshold", "Maximum amount of fluid cell can contain before it is considered empty");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "cache_file_format", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "cache_file_format");
- RNA_def_property_enum_items(prop, cache_file_type_items);
- RNA_def_property_enum_funcs(prop, NULL, "rna_Smoke_cachetype_set", NULL);
- RNA_def_property_ui_text(prop, "File Format", "Select the file format to be used for caching");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- /* display settings */
-
- prop = RNA_def_property(srna, "slice_method", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "slice_method");
- RNA_def_property_enum_items(prop, smoke_view_items);
- RNA_def_property_ui_text(prop, "View Method", "How to slice the volume for viewport rendering");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "axis_slice_method", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "axis_slice_method");
- RNA_def_property_enum_items(prop, axis_slice_method_items);
- RNA_def_property_ui_text(prop, "Method", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- 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_ui_text(prop, "Axis", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "slice_per_voxel", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "slice_per_voxel");
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_range(prop, 0.0, 5.0, 0.1, 1);
- RNA_def_property_ui_text(
- prop, "Slice Per Voxel", "How many slices per voxel should be generated");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "slice_depth", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "slice_depth");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Position", "Position of the slice");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "display_thickness", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "display_thickness");
- RNA_def_property_range(prop, 0.001, 1000.0);
- RNA_def_property_ui_range(prop, 0.1, 100.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Thickness", "Thickness of smoke drawing in the viewport");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
-
- prop = RNA_def_property(srna, "display_interpolation", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "interp_method");
- RNA_def_property_enum_items(prop, interp_method_item);
- RNA_def_property_ui_text(
- prop, "Interpolation", "Interpolation method to use for smoke/fire volumes in solid mode");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "show_velocity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw_velocity", 0);
- RNA_def_property_ui_text(
- prop, "Display Velocity", "Toggle visualization of the velocity field as needles");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "vector_display_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "vector_draw_type");
- RNA_def_property_enum_items(prop, vector_draw_items);
- RNA_def_property_ui_text(prop, "Display Type", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "vector_scale", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "vector_scale");
- RNA_def_property_range(prop, 0.0, 1000.0);
- RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Scale", "Multiplier for scaling the vectors");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- /* --------- Color mapping. --------- */
-
- prop = RNA_def_property(srna, "use_color_ramp", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "use_coba", 0);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_Smoke_use_color_ramp_set");
- RNA_def_property_ui_text(
- prop,
- "Use Color Ramp",
- "Render a simulation field while mapping its voxels values to the colors of a ramp");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- static const EnumPropertyItem coba_field_items[] = {
- {FLUID_FIELD_COLOR_R, "COLOR_R", 0, "Red", "Red component of the color field"},
- {FLUID_FIELD_COLOR_G, "COLOR_G", 0, "Green", "Green component of the color field"},
- {FLUID_FIELD_COLOR_B, "COLOR_B", 0, "Blue", "Blue component of the color field"},
- {FLUID_FIELD_DENSITY, "DENSITY", 0, "Density", "Quantity of soot in the fluid"},
- {FLUID_FIELD_FLAME, "FLAME", 0, "Flame", "Flame field"},
- {FLUID_FIELD_FUEL, "FUEL", 0, "Fuel", "Fuel field"},
- {FLUID_FIELD_HEAT, "HEAT", 0, "Heat", "Temperature of the fluid"},
- {FLUID_FIELD_VELOCITY_X, "VELOCITY_X", 0, "X Velocity", "X component of the velocity field"},
- {FLUID_FIELD_VELOCITY_Y, "VELOCITY_Y", 0, "Y Velocity", "Y component of the velocity field"},
- {FLUID_FIELD_VELOCITY_Z, "VELOCITY_Z", 0, "Z Velocity", "Z component of the velocity field"},
- {0, NULL, 0, NULL, NULL},
- };
-
- prop = RNA_def_property(srna, "coba_field", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "coba_field");
- RNA_def_property_enum_items(prop, coba_field_items);
- RNA_def_property_ui_text(prop, "Field", "Simulation field to color map");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "coba");
- RNA_def_property_struct_type(prop, "ColorRamp");
- RNA_def_property_ui_text(prop, "Color Ramp", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "clipping", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "clipping");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3);
- RNA_def_property_ui_text(
- prop,
- "Clipping",
- "Value under which voxels are considered empty space to optimize caching and rendering");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
-}
-
-static void rna_def_smoke_flow_settings(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static const EnumPropertyItem smoke_flow_types[] = {
- {MOD_SMOKE_FLOW_TYPE_OUTFLOW, "OUTFLOW", 0, "Outflow", "Delete smoke from simulation"},
- {MOD_SMOKE_FLOW_TYPE_SMOKE, "SMOKE", 0, "Smoke", "Add smoke"},
- {MOD_SMOKE_FLOW_TYPE_SMOKEFIRE, "BOTH", 0, "Fire + Smoke", "Add fire and smoke"},
- {MOD_SMOKE_FLOW_TYPE_FIRE, "FIRE", 0, "Fire", "Add fire"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem smoke_flow_sources[] = {
- {MOD_SMOKE_FLOW_SOURCE_PARTICLES,
- "PARTICLES",
- ICON_PARTICLES,
- "Particle System",
- "Emit smoke from particles"},
- {MOD_SMOKE_FLOW_SOURCE_MESH,
- "MESH",
- ICON_META_CUBE,
- "Mesh",
- "Emit smoke from mesh surface or volume"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem smoke_flow_texture_types[] = {
- {MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO,
- "AUTO",
- 0,
- "Generated",
- "Generated coordinates centered to flow object"},
- {MOD_SMOKE_FLOW_TEXTURE_MAP_UV, "UV", 0, "UV", "Use UV layer for texture coordinates"},
- {0, NULL, 0, NULL, NULL},
- };
-
- srna = RNA_def_struct(brna, "SmokeFlowSettings", NULL);
- RNA_def_struct_ui_text(srna, "Flow Settings", "Smoke flow settings");
- RNA_def_struct_sdna(srna, "SmokeFlowSettings");
- RNA_def_struct_path_func(srna, "rna_SmokeFlowSettings_path");
-
- prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "density");
- RNA_def_property_range(prop, 0.0, 1);
- RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 4);
- RNA_def_property_ui_text(prop, "Density", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "color");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "fuel_amount", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 10);
- RNA_def_property_ui_range(prop, 0.0, 5.0, 1.0, 4);
- RNA_def_property_ui_text(prop, "Flame Rate", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "temperature", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "temp");
- RNA_def_property_range(prop, -10, 10);
- RNA_def_property_ui_range(prop, -10, 10, 1, 1);
- RNA_def_property_ui_text(prop, "Temp. Diff.", "Temperature difference to ambient temperature");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "psys");
- RNA_def_property_struct_type(prop, "ParticleSystem");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object");
- RNA_def_property_update(prop, 0, "rna_Smoke_reset_dependency");
-
- prop = RNA_def_property(srna, "smoke_flow_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, smoke_flow_types);
- RNA_def_property_ui_text(prop, "Flow Type", "Change how flow affects the simulation");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "smoke_flow_source", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "source");
- RNA_def_property_enum_items(prop, smoke_flow_sources);
- RNA_def_property_ui_text(prop, "Source", "Change how smoke is emitted");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "use_absolute", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_ABSOLUTE);
- RNA_def_property_ui_text(
- prop, "Absolute Density", "Only allow given density value in emitter area");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "use_initial_velocity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_INITVELOCITY);
- RNA_def_property_ui_text(
- prop, "Initial Velocity", "Smoke has some initial velocity when it is emitted");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "vel_multi");
- RNA_def_property_range(prop, -100.0, 100.0);
- RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
- RNA_def_property_ui_text(prop, "Source", "Multiplier of source velocity passed to smoke");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "velocity_normal", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "vel_normal");
- RNA_def_property_range(prop, -100.0, 100.0);
- RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
- RNA_def_property_ui_text(prop, "Normal", "Amount of normal directional velocity");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "velocity_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "vel_random");
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_range(prop, 0.0, 2.0, 0.05, 5);
- RNA_def_property_ui_text(prop, "Random", "Amount of random velocity");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "volume_density", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_range(prop, 0.0, 1.0, 0.05, 5);
- RNA_def_property_ui_text(prop, "Volume", "Factor for smoke emitted from inside the mesh volume");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_range(prop, 0.5, 5.0, 0.05, 5);
- RNA_def_property_ui_text(prop, "Surface", "Maximum distance from mesh surface to emit smoke");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "particle_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.1, 20.0);
- RNA_def_property_ui_range(prop, 0.5, 5.0, 0.05, 5);
- RNA_def_property_ui_text(prop, "Size", "Particle size in simulation cells");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "use_particle_size", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_USE_PART_SIZE);
- RNA_def_property_ui_text(
- prop, "Set Size", "Set particle size in simulation cells or use nearest cell");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "subframes", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, 50);
- 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 flows");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "density_vertex_group", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop,
- "rna_SmokeFlow_density_vgroup_get",
- "rna_SmokeFlow_density_vgroup_length",
- "rna_SmokeFlow_density_vgroup_set");
- RNA_def_property_ui_text(
- prop, "Vertex Group", "Name of vertex group which determines surface emission rate");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "use_texture", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_TEXTUREEMIT);
- RNA_def_property_ui_text(prop, "Use Texture", "Use a texture to control emission strength");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "texture_map_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "texture_type");
- RNA_def_property_enum_items(prop, smoke_flow_texture_types);
- RNA_def_property_ui_text(prop, "Mapping", "Texture mapping type");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "uvlayer_name");
- RNA_def_property_ui_text(prop, "UV Map", "UV map name");
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SmokeFlow_uvlayer_set");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "noise_texture", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Texture", "Texture that controls emission strength");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "texture_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.01, 10.0);
- RNA_def_property_ui_range(prop, 0.1, 5.0, 0.05, 5);
- RNA_def_property_ui_text(prop, "Size", "Size of texture mapping");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-
- prop = RNA_def_property(srna, "texture_offset", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 200.0);
- RNA_def_property_ui_range(prop, 0.0, 100.0, 0.05, 5);
- RNA_def_property_ui_text(prop, "Offset", "Z-offset of texture mapping");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-}
-
-static void rna_def_smoke_coll_settings(BlenderRNA *brna)
-{
- static const EnumPropertyItem smoke_coll_type_items[] = {
- {SM_COLL_STATIC, "COLLSTATIC", 0, "Static", "Non moving obstacle"},
- {SM_COLL_RIGID, "COLLRIGID", 0, "Rigid", "Rigid obstacle"},
- {SM_COLL_ANIMATED, "COLLANIMATED", 0, "Animated", "Animated obstacle"},
- {0, NULL, 0, NULL, NULL},
- };
-
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "SmokeCollSettings", NULL);
- RNA_def_struct_ui_text(srna, "Collision Settings", "Smoke collision settings");
- RNA_def_struct_sdna(srna, "SmokeCollSettings");
- RNA_def_struct_path_func(srna, "rna_SmokeCollSettings_path");
-
- prop = RNA_def_property(srna, "collision_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, smoke_coll_type_items);
- RNA_def_property_ui_text(prop, "Collision Type", "Collision type");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
-}
-
-void RNA_def_smoke(BlenderRNA *brna)
-{
- rna_def_smoke_domain_settings(brna);
- rna_def_smoke_flow_settings(brna);
- rna_def_smoke_coll_settings(brna);
-}
-
-#endif
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index e0232431930..ffc7425adaa 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -31,7 +31,6 @@ set(INC
../makesdna
../makesrna
../render/extern/include
- ../../../intern/elbeem/extern
../../../intern/eigen
../../../intern/guardedalloc
)
@@ -59,8 +58,7 @@ set(SRC
intern/MOD_dynamicpaint.c
intern/MOD_edgesplit.c
intern/MOD_explode.c
- intern/MOD_fluidsim.c
- intern/MOD_fluidsim_util.c
+ intern/MOD_fluid.c
intern/MOD_functiondeform_cxx.cc
intern/MOD_functiondeform.c
intern/MOD_functionpoints_cxx.cc
@@ -89,7 +87,6 @@ set(SRC
intern/MOD_shrinkwrap.c
intern/MOD_simpledeform.c
intern/MOD_skin.c
- intern/MOD_smoke.c
intern/MOD_smooth.c
intern/MOD_softbody.c
intern/MOD_solidify.c
@@ -113,7 +110,6 @@ set(SRC
intern/MOD_wireframe.c
MOD_modifiertypes.h
- intern/MOD_fluidsim_util.h
intern/MOD_meshcache_util.h
intern/MOD_solidify_util.h
intern/MOD_util.h
@@ -148,7 +144,7 @@ if(WITH_MOD_REMESH)
endif()
if(WITH_MOD_FLUID)
- add_definitions(-DWITH_MOD_FLUID)
+ add_definitions(-DWITH_FLUID)
endif()
if(WITH_MOD_OCEANSIM)
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 0560ed86c75..5668b518195 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -56,7 +56,7 @@ extern ModifierTypeInfo modifierType_Mask;
extern ModifierTypeInfo modifierType_SimpleDeform;
extern ModifierTypeInfo modifierType_Multires;
extern ModifierTypeInfo modifierType_Surface;
-extern ModifierTypeInfo modifierType_Smoke;
+extern ModifierTypeInfo modifierType_Fluid;
extern ModifierTypeInfo modifierType_ShapeKey;
extern ModifierTypeInfo modifierType_Solidify;
extern ModifierTypeInfo modifierType_Screw;
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_fluid.c
index 34275d91ee6..b48c80d8e32 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_fluid.c
@@ -30,7 +30,7 @@
#include "DNA_collection_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_smoke_types.h"
+#include "DNA_fluid_types.h"
#include "DNA_object_force_types.h"
#include "DNA_mesh_types.h"
@@ -38,7 +38,7 @@
#include "BKE_layer.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "BKE_smoke.h"
+#include "BKE_fluid.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -49,45 +49,53 @@
static void initData(ModifierData *md)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
+ FluidModifierData *mmd = (FluidModifierData *)md;
- smd->domain = NULL;
- smd->flow = NULL;
- smd->coll = NULL;
- smd->type = 0;
- smd->time = -1;
+ mmd->domain = NULL;
+ mmd->flow = NULL;
+ mmd->effector = NULL;
+ mmd->type = 0;
+ mmd->time = -1;
}
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
{
- const SmokeModifierData *smd = (const SmokeModifierData *)md;
- SmokeModifierData *tsmd = (SmokeModifierData *)target;
-
- smokeModifier_free(tsmd);
- smokeModifier_copy(smd, tsmd, flag);
+#ifndef WITH_FLUID
+ UNUSED_VARS(md, target, flag);
+#else
+ const FluidModifierData *mmd = (const FluidModifierData *)md;
+ FluidModifierData *tmmd = (FluidModifierData *)target;
+
+ BKE_fluid_modifier_free(tmmd);
+ BKE_fluid_modifier_copy(mmd, tmmd, flag);
+#endif /* WITH_FLUID */
}
static void freeData(ModifierData *md)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
+#ifndef WITH_FLUID
+ UNUSED_VARS(md);
+#else
+ FluidModifierData *mmd = (FluidModifierData *)md;
- smokeModifier_free(smd);
+ BKE_fluid_modifier_free(mmd);
+#endif /* WITH_FLUID */
}
static void requiredDataMask(Object *UNUSED(ob),
ModifierData *md,
CustomData_MeshMasks *r_cddata_masks)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
+ FluidModifierData *mmd = (FluidModifierData *)md;
- if (smd && (smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
- if (smd->flow->source == MOD_SMOKE_FLOW_SOURCE_MESH) {
+ if (mmd && (mmd->type & MOD_FLUID_TYPE_FLOW) && mmd->flow) {
+ if (mmd->flow->source == FLUID_FLOW_SOURCE_MESH) {
/* vertex groups */
- if (smd->flow->vgroup_density) {
+ if (mmd->flow->vgroup_density) {
r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
}
/* uv layer */
- if (smd->flow->texture_type == MOD_SMOKE_FLOW_TEXTURE_MAP_UV) {
+ if (mmd->flow->texture_type == FLUID_FLOW_TEXTURE_MAP_UV) {
r_cddata_masks->fmask |= CD_MASK_MTFACE;
}
}
@@ -96,14 +104,22 @@ static void requiredDataMask(Object *UNUSED(ob),
static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
+#ifndef WITH_FLUID
+ UNUSED_VARS(md, ctx);
+ return me;
+#else
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ Mesh *result = NULL;
if (ctx->flag & MOD_APPLY_ORCO) {
return me;
}
Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
- return smokeModifier_do(smd, ctx->depsgraph, scene, ctx->object, me);
+
+ result = BKE_fluid_modifier_do(mmd, ctx->depsgraph, scene, ctx->object, me);
+ return result ? result : me;
+#endif /* WITH_FLUID */
}
static bool dependsOnTime(ModifierData *UNUSED(md))
@@ -113,68 +129,78 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
static bool is_flow_cb(Object *UNUSED(ob), ModifierData *md)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
- return (smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow;
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ return (mmd->type & MOD_FLUID_TYPE_FLOW) && mmd->flow;
}
static bool is_coll_cb(Object *UNUSED(ob), ModifierData *md)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
- return (smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll;
+ FluidModifierData *mmd = (FluidModifierData *)md;
+ return (mmd->type & MOD_FLUID_TYPE_EFFEC) && mmd->effector;
}
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
+ FluidModifierData *mmd = (FluidModifierData *)md;
- if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
+ if (mmd && (mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain) {
DEG_add_collision_relations(ctx->node,
ctx->object,
- smd->domain->fluid_group,
- eModifierType_Smoke,
+ mmd->domain->fluid_group,
+ eModifierType_Fluid,
is_flow_cb,
- "Smoke Flow");
+ "Fluid Flow");
DEG_add_collision_relations(ctx->node,
ctx->object,
- smd->domain->coll_group,
- eModifierType_Smoke,
+ mmd->domain->effector_group,
+ eModifierType_Fluid,
is_coll_cb,
- "Smoke Coll");
+ "Fluid Effector");
DEG_add_forcefield_relations(ctx->node,
ctx->object,
- smd->domain->effector_weights,
+ mmd->domain->effector_weights,
true,
PFIELD_SMOKEFLOW,
- "Smoke Force Field");
+ "Fluid Force Field");
+
+ if (mmd->domain->guide_parent != NULL) {
+ DEG_add_object_relation(
+ ctx->node, mmd->domain->guide_parent, DEG_OB_COMP_TRANSFORM, "Fluid Guiding Object");
+ DEG_add_object_relation(
+ ctx->node, mmd->domain->guide_parent, DEG_OB_COMP_GEOMETRY, "Fluid Guiding Object");
+ }
}
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
- SmokeModifierData *smd = (SmokeModifierData *)md;
+ FluidModifierData *mmd = (FluidModifierData *)md;
+
+ if (mmd->type == MOD_FLUID_TYPE_DOMAIN && mmd->domain) {
+ walk(userData, ob, (ID **)&mmd->domain->effector_group, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&mmd->domain->fluid_group, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&mmd->domain->force_group, IDWALK_CB_NOP);
- if (smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
- walk(userData, ob, (ID **)&smd->domain->coll_group, IDWALK_CB_NOP);
- walk(userData, ob, (ID **)&smd->domain->fluid_group, IDWALK_CB_NOP);
- walk(userData, ob, (ID **)&smd->domain->eff_group, IDWALK_CB_NOP);
+ if (mmd->domain->guide_parent) {
+ walk(userData, ob, (ID **)&mmd->domain->guide_parent, IDWALK_CB_NOP);
+ }
- if (smd->domain->effector_weights) {
- walk(userData, ob, (ID **)&smd->domain->effector_weights->group, IDWALK_CB_NOP);
+ if (mmd->domain->effector_weights) {
+ walk(userData, ob, (ID **)&mmd->domain->effector_weights->group, IDWALK_CB_NOP);
}
}
- if (smd->type == MOD_SMOKE_TYPE_FLOW && smd->flow) {
- walk(userData, ob, (ID **)&smd->flow->noise_texture, IDWALK_CB_USER);
+ if (mmd->type == MOD_FLUID_TYPE_FLOW && mmd->flow) {
+ walk(userData, ob, (ID **)&mmd->flow->noise_texture, IDWALK_CB_USER);
}
}
-ModifierTypeInfo modifierType_Smoke = {
- /* name */ "Smoke",
- /* structName */ "SmokeModifierData",
- /* structSize */ sizeof(SmokeModifierData),
+ModifierTypeInfo modifierType_Fluid = {
+ /* name */ "Fluid",
+ /* structName */ "FluidModifierData",
+ /* structSize */ sizeof(FluidModifierData),
/* type */ eModifierTypeType_Constructive,
- /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_UsesPointCache |
- eModifierTypeFlag_Single,
+ /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_Single,
/* copyData */ copyData,
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
deleted file mode 100644
index 620b21f3e0c..00000000000
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 by the Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup modifiers
- */
-
-#include "BLI_utildefines.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_fluidsim_types.h"
-#include "DNA_object_types.h"
-
-#include "BKE_layer.h"
-#include "BKE_modifier.h"
-
-#include "DEG_depsgraph_build.h"
-
-#include "MOD_fluidsim_util.h"
-#include "MOD_modifiertypes.h"
-
-#include "MEM_guardedalloc.h"
-
-/* Fluidsim */
-static void initData(ModifierData *md)
-{
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
-
- fluidsim_init(fluidmd);
-}
-static void freeData(ModifierData *md)
-{
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
-
- fluidsim_free(fluidmd);
-}
-
-static void copyData(const ModifierData *md, ModifierData *target, const int UNUSED(flag))
-{
- const FluidsimModifierData *fluidmd = (const FluidsimModifierData *)md;
- FluidsimModifierData *tfluidmd = (FluidsimModifierData *)target;
-
- /* Free any FSS that was allocated in initData() */
- if (tfluidmd->fss) {
- MEM_SAFE_FREE(tfluidmd->fss->meshVelocities);
- MEM_freeN(tfluidmd->fss);
- }
-
- if (fluidmd->fss == NULL) {
- tfluidmd->fss = NULL;
- return;
- }
-
- tfluidmd->fss = MEM_dupallocN(fluidmd->fss);
- if (tfluidmd->fss->meshVelocities != NULL) {
- tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities);
- }
-}
-
-static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
-{
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
- Mesh *result = NULL;
-
- /* check for alloc failing */
- if (!fluidmd->fss) {
- initData(md);
-
- if (!fluidmd->fss) {
- return mesh;
- }
- }
-
- result = fluidsimModifier_do(fluidmd, ctx, mesh);
-
- return result ? result : mesh;
-}
-
-static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
-{
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
- if (fluidmd && fluidmd->fss) {
- if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) {
- FOREACH_SCENE_OBJECT_BEGIN (ctx->scene, ob1) {
- if (ob1 != ctx->object) {
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(
- ob1, eModifierType_Fluidsim);
-
- /* Only put dependencies from NON-DOMAIN fluids in here. */
- if (fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN)) {
- DEG_add_object_relation(ctx->node, ob1, DEG_OB_COMP_TRANSFORM, "Fluidsim Object");
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
- }
- }
-}
-
-static bool dependsOnTime(ModifierData *UNUSED(md))
-{
- return true;
-}
-
-ModifierTypeInfo modifierType_Fluidsim = {
- /* name */ "Fluidsim",
- /* structName */ "FluidsimModifierData",
- /* structSize */ sizeof(FluidsimModifierData),
- /* type */ eModifierTypeType_Nonconstructive,
-
- /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData |
- eModifierTypeFlag_Single,
-
- /* copyData */ copyData,
-
- /* deformVerts */ NULL,
- /* deformMatrices */ NULL,
- /* deformVertsEM */ NULL,
- /* deformMatricesEM */ NULL,
- /* applyModifier */ applyModifier,
-
- /* initData */ initData,
- /* requiredDataMask */ NULL,
- /* freeData */ freeData,
- /* isDisabled */ NULL,
- /* updateDepsgraph */ updateDepsgraph,
- /* dependsOnTime */ dependsOnTime,
- /* dependsOnNormals */ NULL,
- /* foreachObjectLink */ NULL,
- /* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
- /* freeRuntimeData */ NULL,
-};
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c
deleted file mode 100644
index 748bf4db4e2..00000000000
--- a/source/blender/modifiers/intern/MOD_fluidsim_util.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 by the Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup modifiers
- */
-
-#include <stddef.h>
-#include <zlib.h>
-
-#include "BLI_utildefines.h"
-
-#ifdef WITH_MOD_FLUID
-# include "BLI_blenlib.h"
-# include "BLI_math.h"
-#endif
-
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_fluidsim_types.h"
-
-#include "BKE_fluidsim.h" /* ensure definitions here match */
-#include "BKE_mesh.h"
-#ifdef WITH_MOD_FLUID
-# include "BKE_global.h"
-# include "BKE_library.h"
-#endif
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
-
-#include "MOD_fluidsim_util.h"
-#include "MOD_modifiertypes.h"
-
-#include "MEM_guardedalloc.h"
-
-// headers for fluidsim bobj meshes
-#include "LBM_fluidsim.h"
-
-void fluidsim_init(FluidsimModifierData *fluidmd)
-{
-#ifdef WITH_MOD_FLUID
- if (fluidmd) {
- FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");
-
- fluidmd->fss = fss;
-
- if (!fss) {
- return;
- }
-
- fss->fmd = fluidmd;
- fss->type = OB_FLUIDSIM_ENABLE;
- fss->threads = 0;
- fss->show_advancedoptions = 0;
-
- fss->resolutionxyz = 65;
- fss->previewresxyz = 45;
- fss->realsize = 0.5;
- fss->guiDisplayMode = OB_FSDOM_PREVIEW;
- fss->renderDisplayMode = OB_FSDOM_FINAL;
-
- fss->viscosityValue = 1.0;
- fss->viscosityExponent = 6;
-
- fss->grav[0] = 0.0;
- fss->grav[1] = 0.0;
- fss->grav[2] = -9.81;
-
- fss->animStart = 0.0;
- fss->animEnd = 4.0;
- fss->animRate = 1.0;
- fss->gstar = 0.005; // used as normgstar
- fss->maxRefine = -1;
- /* maxRefine is set according to resolutionxyz during bake */
-
- /* fluid/inflow settings
- * fss->iniVel --> automatically set to 0 */
-
- modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), OB_FLUIDSIM_SURF_DIR_DEFAULT);
-
- /* first init of bounding box */
- /* no bounding box needed */
-
- /* todo - reuse default init from elbeem! */
- fss->typeFlags = OB_FSBND_PARTSLIP | OB_FSSG_NOOBS;
- fss->domainNovecgen = 0;
- fss->volumeInitType = 1; /* volume */
- fss->partSlipValue = 0.2;
-
- fss->generateTracers = 0;
- fss->generateParticles = 0.0;
- fss->surfaceSmoothing = 1.0;
- fss->surfaceSubdivs = 0.0;
- fss->particleInfSize = 0.0;
- fss->particleInfAlpha = 0.0;
-
- /* init fluid control settings */
- fss->attractforceStrength = 0.2;
- fss->attractforceRadius = 0.75;
- fss->velocityforceStrength = 0.2;
- fss->velocityforceRadius = 0.75;
- fss->cpsTimeStart = fss->animStart;
- fss->cpsTimeEnd = fss->animEnd;
- fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
-
- /*
- * BAD TODO: this is done in buttons_object.c in the moment
- * Mesh *mesh = ob->data;
- * // calculate bounding box
- * fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
- */
-
- fss->meshVelocities = NULL;
-
- fss->lastgoodframe = -1;
-
- fss->flag |= OB_FLUIDSIM_ACTIVE;
- }
-#else
- (void)fluidmd; /* unused */
-#endif
- return;
-}
-
-void fluidsim_free(FluidsimModifierData *fluidmd)
-{
- if (fluidmd && fluidmd->fss) {
- if (fluidmd->fss->meshVelocities) {
- MEM_freeN(fluidmd->fss->meshVelocities);
- }
- MEM_SAFE_FREE(fluidmd->fss);
- }
-
- return;
-}
-
-#ifdef WITH_MOD_FLUID
-/* read .bobj.gz file into a fluidsimMesh struct */
-static Mesh *fluidsim_read_obj(const char *filename, const MPoly *mp_example)
-{
- int wri = 0, i;
- int gotBytes;
- gzFile gzf;
- int numverts = 0, numfaces = 0;
- Mesh *mesh = NULL;
- MPoly *mp;
- MLoop *ml;
- MVert *mv;
- short *normals, *no_s;
- float no[3];
-
- const short mp_mat_nr = mp_example->mat_nr;
- const char mp_flag = mp_example->flag;
-
- /* ------------------------------------------------
- * get numverts + numfaces first
- * ------------------------------------------------ */
- gzf = BLI_gzopen(filename, "rb");
- if (!gzf) {
- return NULL;
- }
-
- /* read numverts */
- gotBytes = gzread(gzf, &wri, sizeof(wri));
- numverts = wri;
-
- /* skip verts */
- gotBytes = gzseek(gzf, numverts * 3 * sizeof(float), SEEK_CUR) != -1;
-
- /* read number of normals */
- if (gotBytes) {
- gotBytes = gzread(gzf, &wri, sizeof(wri));
- }
-
- /* skip normals */
- gotBytes = gzseek(gzf, numverts * 3 * sizeof(float), SEEK_CUR) != -1;
-
- /* get no. of triangles */
- if (gotBytes) {
- gotBytes = gzread(gzf, &wri, sizeof(wri));
- }
- numfaces = wri;
-
- gzclose(gzf);
- /* ------------------------------------------------ */
-
- if (!numfaces || !numverts || !gotBytes) {
- return NULL;
- }
-
- gzf = BLI_gzopen(filename, "rb");
- if (!gzf) {
- return NULL;
- }
-
- mesh = BKE_mesh_new_nomain(numverts, 0, 0, numfaces * 3, numfaces);
-
- if (!mesh) {
- gzclose(gzf);
- return NULL;
- }
-
- /* read numverts */
- gotBytes = gzread(gzf, &wri, sizeof(wri));
-
- /* read vertex position from file */
- mv = mesh->mvert;
-
- for (i = 0; i < numverts; i++, mv++) {
- gotBytes = gzread(gzf, mv->co, sizeof(float) * 3);
- }
-
- /* should be the same as numverts */
- gotBytes = gzread(gzf, &wri, sizeof(wri));
- if (wri != numverts) {
- if (mesh) {
- BKE_id_free(NULL, mesh);
- }
- gzclose(gzf);
- return NULL;
- }
-
- normals = MEM_calloc_arrayN(numverts, 3 * sizeof(short), "fluid_tmp_normals");
- if (!normals) {
- if (mesh) {
- BKE_id_free(NULL, mesh);
- }
- gzclose(gzf);
- return NULL;
- }
-
- /* read normals from file (but don't save them yet) */
- for (i = numverts, no_s = normals; i > 0; i--, no_s += 3) {
- gotBytes = gzread(gzf, no, sizeof(float) * 3);
- normal_float_to_short_v3(no_s, no);
- }
-
- /* read no. of triangles */
- gotBytes = gzread(gzf, &wri, sizeof(wri));
-
- if (wri != numfaces) {
- printf("Fluidsim: error in reading data from file.\n");
- if (mesh) {
- BKE_id_free(NULL, mesh);
- }
- gzclose(gzf);
- MEM_freeN(normals);
- return NULL;
- }
-
- /* read triangles from file */
- mp = mesh->mpoly;
- ml = mesh->mloop;
- for (i = 0; i < numfaces; i++, mp++, ml += 3) {
- int face[3];
-
- gotBytes = gzread(gzf, face, sizeof(int) * 3);
-
- /* initialize from existing face */
- mp->mat_nr = mp_mat_nr;
- mp->flag = mp_flag;
-
- mp->loopstart = i * 3;
- mp->totloop = 3;
-
- ml[0].v = face[0];
- ml[1].v = face[1];
- ml[2].v = face[2];
- }
-
- gzclose(gzf);
-
- BKE_mesh_calc_edges(mesh, false, false);
- BKE_mesh_vert_normals_apply(mesh, (short(*)[3])normals);
- MEM_freeN(normals);
-
- // CDDM_calc_normals(result);
- return mesh;
-}
-
-void fluid_get_bb(MVert *mvert,
- int totvert,
- float obmat[4][4],
- /*RET*/ float start[3],
- /*RET*/ float size[3])
-{
- float bbsx = 0.0, bbsy = 0.0, bbsz = 0.0;
- float bbex = 1.0, bbey = 1.0, bbez = 1.0;
- int i;
- float vec[3];
-
- if (totvert == 0) {
- zero_v3(start);
- zero_v3(size);
- return;
- }
-
- copy_v3_v3(vec, mvert[0].co);
- mul_m4_v3(obmat, vec);
- bbsx = vec[0];
- bbsy = vec[1];
- bbsz = vec[2];
- bbex = vec[0];
- bbey = vec[1];
- bbez = vec[2];
-
- for (i = 1; i < totvert; i++) {
- copy_v3_v3(vec, mvert[i].co);
- mul_m4_v3(obmat, vec);
-
- if (vec[0] < bbsx) {
- bbsx = vec[0];
- }
- if (vec[1] < bbsy) {
- bbsy = vec[1];
- }
- if (vec[2] < bbsz) {
- bbsz = vec[2];
- }
- if (vec[0] > bbex) {
- bbex = vec[0];
- }
- if (vec[1] > bbey) {
- bbey = vec[1];
- }
- if (vec[2] > bbez) {
- bbez = vec[2];
- }
- }
-
- /* return values... */
- if (start) {
- start[0] = bbsx;
- start[1] = bbsy;
- start[2] = bbsz;
- }
- if (size) {
- size[0] = bbex - bbsx;
- size[1] = bbey - bbsy;
- size[2] = bbez - bbsz;
- }
-}
-
-//-------------------------------------------------------------------------------
-// old interface
-//-------------------------------------------------------------------------------
-
-void fluid_estimate_memory(Object *ob, FluidsimSettings *fss, char *value)
-{
- Mesh *mesh;
-
- value[0] = '\0';
-
- if (ob->type == OB_MESH) {
- /* use mesh bounding box and object scaling */
- mesh = ob->data;
-
- fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
- elbeemEstimateMemreq(
- fss->resolutionxyz, fss->bbSize[0], fss->bbSize[1], fss->bbSize[2], fss->maxRefine, value);
- }
-}
-
-/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
-static void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, Mesh *mesh, char *filename)
-{
- int wri, i, j;
- float wrf;
- gzFile gzf;
- FluidsimSettings *fss = fluidmd->fss;
- int len = strlen(filename);
- int totvert = mesh->totvert;
- FluidVertexVelocity *velarray = NULL;
-
- /* mesh and vverts have to be valid from loading... */
-
- if (fss->meshVelocities) {
- MEM_freeN(fss->meshVelocities);
- }
-
- if (len < 7) {
- return;
- }
-
- if (fss->domainNovecgen > 0) {
- return;
- }
-
- fss->meshVelocities = MEM_calloc_arrayN(
- mesh->totvert, sizeof(FluidVertexVelocity), "Fluidsim_velocities");
- fss->totvert = totvert;
-
- velarray = fss->meshVelocities;
-
- /* .bobj.gz, correct filename
- * 87654321 */
- filename[len - 6] = 'v';
- filename[len - 5] = 'e';
- filename[len - 4] = 'l';
-
- gzf = BLI_gzopen(filename, "rb");
- if (!gzf) {
- MEM_freeN(fss->meshVelocities);
- fss->meshVelocities = NULL;
- return;
- }
-
- gzread(gzf, &wri, sizeof(wri));
- if (wri != totvert) {
- MEM_freeN(fss->meshVelocities);
- fss->meshVelocities = NULL;
- return;
- }
-
- for (i = 0; i < totvert; i++) {
- for (j = 0; j < 3; j++) {
- gzread(gzf, &wrf, sizeof(wrf));
- velarray[i].vel[j] = wrf;
- }
- }
-
- gzclose(gzf);
-}
-
-static Mesh *fluidsim_read_cache(
- Object *ob, Mesh *orgmesh, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
-{
- int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */
- /* why start with 0 as start frame?? Animations + time are frozen for frame 0 anyway.
- * (See physics_fluid.c for that. - DG) */
- /* If we start with frame 0, we need to remap all animation channels, too,
- * because they will all be 1 frame late if using frame-1! - DG */
-
- char targetFile[FILE_MAX];
- FluidsimSettings *fss = fluidmd->fss;
- Mesh *newmesh = NULL;
- MPoly *mpoly;
- MPoly mp_example = {0};
-
- const int displaymode = useRenderParams ? fss->renderDisplayMode : fss->guiDisplayMode;
-
- switch (displaymode) {
- case OB_FSDOM_GEOM:
- /* just display original object */
- return NULL;
- case OB_FSDOM_PREVIEW:
- /* use preview mesh */
- BLI_join_dirfile(
- targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME);
- break;
- case OB_FSDOM_FINAL:
- /* use final mesh */
- BLI_join_dirfile(
- targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
- break;
- default:
- BLI_assert(!"Wrong fluidsim display type");
- return NULL;
- }
-
- /* offset baked frame */
- curFrame += fss->frameOffset;
-
- BLI_path_abs(targetFile, modifier_path_relbase_from_global(ob));
- BLI_path_frame(targetFile, curFrame, 0); // fixed #frame-no
-
- /* assign material + flags to new mesh.
- * if there's no faces in original mesh, keep materials and flags unchanged */
- mpoly = orgmesh->mpoly;
- if (mpoly) {
- mp_example = *mpoly;
- }
- /* else leave NULL'd */
-
- newmesh = fluidsim_read_obj(targetFile, &mp_example);
-
- if (!newmesh) {
- /* switch, abort background rendering when fluidsim mesh is missing */
- const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
-
- if (G.background == 1) {
- if (BLI_getenv(strEnvName2)) {
- int elevel = atoi(BLI_getenv(strEnvName2));
- if (elevel > 0) {
- printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",
- strEnvName2,
- targetFile);
- exit(1);
- }
- }
- }
-
- /* display org. object upon failure which is in new mesh */
- return NULL;
- }
-
- BKE_mesh_copy_settings(newmesh, orgmesh);
-
- /* Fluid simulation has a texture space that based on the bounds of the fluid mesh.
- * This does not seem particularly useful, but it's backwards compatible. */
- BKE_mesh_texspace_calc(newmesh);
-
- /* load vertex velocities, if they exist...
- * TODO? use generate flag as loading flag as well?
- * warning, needs original .bobj.gz mesh loading filename */
- if (displaymode == OB_FSDOM_FINAL) {
- fluidsim_read_vel_cache(fluidmd, newmesh, targetFile);
- }
- else {
- if (fss->meshVelocities) {
- MEM_freeN(fss->meshVelocities);
- }
-
- fss->meshVelocities = NULL;
- }
-
- return newmesh;
-}
-#endif // WITH_MOD_FLUID
-
-Mesh *fluidsimModifier_do(FluidsimModifierData *fluidmd,
- const ModifierEvalContext *ctx,
- Mesh *mesh)
-{
-#ifdef WITH_MOD_FLUID
- Object *ob = ctx->object;
- Depsgraph *depsgraph = ctx->depsgraph;
- const bool useRenderParams = (ctx->flag & MOD_APPLY_RENDER) != 0;
- // const bool isFinalCalc = (ctx->flag & MOD_APPLY_USECACHE) != 0;
- Mesh *result = NULL;
- int framenr;
- FluidsimSettings *fss = NULL;
-
- framenr = (int)DEG_get_ctime(depsgraph);
-
- /* only handle fluidsim domains */
- if (fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN)) {
- return mesh;
- }
-
- /* sanity check */
- if (!fluidmd || !fluidmd->fss) {
- return mesh;
- }
-
- fss = fluidmd->fss;
-
- /* timescale not supported yet
- * clmd->sim_parms->timescale = timescale; */
-
- /* support reversing of baked fluid frames here */
- if ((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0)) {
- framenr = fss->lastgoodframe - framenr + 1;
- CLAMP(framenr, 1, fss->lastgoodframe);
- }
-
- /* try to read from cache */
- /* if the frame is there, fine, otherwise don't do anything */
- if ((result = fluidsim_read_cache(ob, mesh, fluidmd, framenr, useRenderParams))) {
- return result;
- }
-
- return mesh;
-#else
- /* unused */
- UNUSED_VARS(fluidmd, ctx, mesh);
- return NULL;
-#endif
-}
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.h b/source/blender/modifiers/intern/MOD_fluidsim_util.h
deleted file mode 100644
index da70568353e..00000000000
--- a/source/blender/modifiers/intern/MOD_fluidsim_util.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- */
-
-/** \file
- * \ingroup modifiers
- */
-
-#ifndef __MOD_FLUIDSIM_UTIL_H__
-#define __MOD_FLUIDSIM_UTIL_H__
-
-struct FluidsimModifierData;
-struct Mesh;
-struct ModifierEvalContext;
-
-/* new fluid-modifier interface */
-void fluidsim_init(struct FluidsimModifierData *fluidmd);
-void fluidsim_free(struct FluidsimModifierData *fluidmd);
-
-struct Mesh *fluidsimModifier_do(struct FluidsimModifierData *fluidmd,
- const struct ModifierEvalContext *ctx,
- struct Mesh *me);
-
-#endif
diff --git a/source/blender/modifiers/intern/MOD_solidify_util.h b/source/blender/modifiers/intern/MOD_solidify_util.h
index dba360dc1ce..3a9608861dc 100644
--- a/source/blender/modifiers/intern/MOD_solidify_util.h
+++ b/source/blender/modifiers/intern/MOD_solidify_util.h
@@ -18,8 +18,8 @@
* \ingroup modifiers
*/
-#ifndef __MOD_MESHCACHE_UTIL_H__
-#define __MOD_MESHCACHE_UTIL_H__
+#ifndef __MOD_SOLIDIFY_UTIL_H__
+#define __MOD_SOLIDIFY_UTIL_H__
/* MOD_solidify_extrude.c */
Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md,
@@ -31,4 +31,4 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh);
-#endif /* __MOD_MESHCACHE_UTIL_H__ */
+#endif /* __MOD_SOLIDIFY_UTIL_H__ */
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 45ec79d7801..f97fbc224cd 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -279,12 +279,11 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(ParticleInstance);
INIT_TYPE(Explode);
INIT_TYPE(Shrinkwrap);
- INIT_TYPE(Fluidsim);
INIT_TYPE(Mask);
INIT_TYPE(SimpleDeform);
INIT_TYPE(Multires);
INIT_TYPE(Surface);
- INIT_TYPE(Smoke);
+ INIT_TYPE(Fluid);
INIT_TYPE(ShapeKey);
INIT_TYPE(Solidify);
INIT_TYPE(Screw);
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index fb2cb11d269..2eb2a6b380a 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -173,11 +173,11 @@ set(SRC
shader/nodes/node_shader_normal.c
shader/nodes/node_shader_normal_map.c
shader/nodes/node_shader_object_info.c
+ shader/nodes/node_shader_output_aov.c
shader/nodes/node_shader_output_light.c
shader/nodes/node_shader_output_linestyle.c
shader/nodes/node_shader_output_material.c
shader/nodes/node_shader_output_world.c
- shader/nodes/node_shader_output_aov.c
shader/nodes/node_shader_particle_info.c
shader/nodes/node_shader_rgb.c
shader/nodes/node_shader_script.c
diff --git a/source/blender/nodes/composite/nodes/node_composite_denoise.c b/source/blender/nodes/composite/nodes/node_composite_denoise.c
index ac30ed9576d..06c862fc3ab 100644
--- a/source/blender/nodes/composite/nodes/node_composite_denoise.c
+++ b/source/blender/nodes/composite/nodes/node_composite_denoise.c
@@ -1,6 +1,4 @@
/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -19,13 +17,9 @@
* All rights reserved.
*
* The Original Code is: all of this file.
- *
- * Contributor(s): Stefan Werner
- *
- * ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/nodes/composite/nodes/node_composite_denoise.c
+/** \file
* \ingroup cmpnodes
*/
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index d5f0e2fb863..012492fe9a7 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -33,6 +33,7 @@ set(INC
../../windowmanager
../../../../intern/clog
../../../../intern/guardedalloc
+ ../../../../intern/mantaflow/extern
../../../../intern/opencolorio
)
@@ -257,10 +258,6 @@ if(WITH_LIBMV)
add_definitions(-DWITH_LIBMV)
endif()
-if(WITH_MOD_FLUID)
- add_definitions(-DWITH_MOD_FLUID)
-endif()
-
if(WITH_MOD_OCEANSIM)
add_definitions(-DWITH_OCEANSIM)
endif()
@@ -269,8 +266,8 @@ if(WITH_MOD_REMESH)
add_definitions(-DWITH_MOD_REMESH)
endif()
-if(WITH_MOD_SMOKE)
- add_definitions(-DWITH_SMOKE)
+if(WITH_MOD_FLUID)
+ add_definitions(-DWITH_FLUID)
endif()
if(WITH_OPENCOLLADA)
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index ee6a3fd41d8..7d2645e7776 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -51,16 +51,15 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{(char *)"sdl_dynload", NULL},
{(char *)"jack", NULL},
{(char *)"libmv", NULL},
- {(char *)"mod_fluid", NULL},
{(char *)"mod_oceansim", NULL},
{(char *)"mod_remesh", NULL},
- {(char *)"mod_smoke", NULL},
{(char *)"collada", NULL},
{(char *)"opencolorio", NULL},
{(char *)"openmp", NULL},
{(char *)"openvdb", NULL},
{(char *)"alembic", NULL},
{(char *)"usd", NULL},
+ {(char *)"fluid", NULL},
{NULL},
};
@@ -222,12 +221,6 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
-#ifdef WITH_MOD_FLUID
- SetObjIncref(Py_True);
-#else
- SetObjIncref(Py_False);
-#endif
-
#ifdef WITH_OCEANSIM
SetObjIncref(Py_True);
#else
@@ -240,12 +233,6 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
-#ifdef WITH_SMOKE
- SetObjIncref(Py_True);
-#else
- SetObjIncref(Py_False);
-#endif
-
#ifdef WITH_COLLADA
SetObjIncref(Py_True);
#else
@@ -282,6 +269,12 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
+#ifdef WITH_FLUID
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
#undef SetObjIncref
return builtopts_info;
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 2b9556e998a..9acf05abfe2 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -197,8 +197,15 @@ void BPY_context_set(bContext *C)
BPy_SetContext(C);
}
+#ifdef WITH_FLUID
+/* defined in manta module */
+extern PyObject *Manta_initPython(void);
+#endif
+
+#ifdef WITH_AUDASPACE
/* defined in AUD_C-API.cpp */
extern PyObject *AUD_initPython(void);
+#endif
#ifdef WITH_CYCLES
/* defined in cycles module */
@@ -225,6 +232,9 @@ static struct _inittab bpy_internal_modules[] = {
{"bmesh.utils", BPyInit_bmesh_utils},
{"bmesh.utils", BPyInit_bmesh_geometry},
#endif
+#ifdef WITH_FLUID
+ {"manta", Manta_initPython},
+#endif
#ifdef WITH_AUDASPACE
{"aud", AUD_initPython},
#endif
@@ -285,6 +295,13 @@ void BPY_python_start(int argc, const char **argv)
/* Initialize thread support (also acquires lock) */
PyEval_InitThreads();
+
+# ifdef WITH_FLUID
+ /* Required to prevent assertion error, see:
+ * https://stackoverflow.com/questions/27844676 */
+ Py_DECREF(PyImport_ImportModule("threading"));
+# endif
+
#else
(void)argc;
(void)argv;
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index e265197646c..a92be8509d5 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -36,7 +36,7 @@ set(INC
../../../intern/atomic
../../../intern/guardedalloc
../../../intern/mikktspace
- ../../../intern/smoke/extern
+ ../../../intern/mantaflow/extern
)
set(INC_SYS
@@ -86,8 +86,8 @@ if(WITH_IMAGE_OPENEXR)
add_definitions(-DWITH_OPENEXR)
endif()
-if(WITH_MOD_SMOKE)
- add_definitions(-DWITH_SMOKE)
+if(WITH_MOD_FLUID)
+ add_definitions(-DWITH_FLUID)
endif()
if(WITH_FREESTYLE)
diff --git a/source/blender/shader_fx/CMakeLists.txt b/source/blender/shader_fx/CMakeLists.txt
index 57c7345076e..6d918763996 100644
--- a/source/blender/shader_fx/CMakeLists.txt
+++ b/source/blender/shader_fx/CMakeLists.txt
@@ -30,7 +30,6 @@ set(INC
../makesdna
../makesrna
../render/extern/include
- ../../../intern/elbeem/extern
../../../intern/eigen
../../../intern/guardedalloc
)
diff --git a/source/blender/usd/intern/abstract_hierarchy_iterator.h b/source/blender/usd/intern/abstract_hierarchy_iterator.h
index db1e4248cab..ea31e94cf9b 100644
--- a/source/blender/usd/intern/abstract_hierarchy_iterator.h
+++ b/source/blender/usd/intern/abstract_hierarchy_iterator.h
@@ -33,8 +33,8 @@
* Selections like "selected only" or "no hair systems" are left to concrete subclasses.
*/
-#ifndef __USD__ABSTRACT_HIERARCHY_ITERATOR_H__
-#define __USD__ABSTRACT_HIERARCHY_ITERATOR_H__
+#ifndef __ABSTRACT_HIERARCHY_ITERATOR_H__
+#define __ABSTRACT_HIERARCHY_ITERATOR_H__
#include <map>
#include <string>
@@ -245,4 +245,4 @@ class AbstractHierarchyIterator {
} // namespace USD
-#endif /* __USD__ABSTRACT_HIERARCHY_ITERATOR_H__ */
+#endif /* __ABSTRACT_HIERARCHY_ITERATOR_H__ */
diff --git a/source/blender/usd/intern/usd_exporter_context.h b/source/blender/usd/intern/usd_exporter_context.h
index aaa0121807c..35ff13b2e91 100644
--- a/source/blender/usd/intern/usd_exporter_context.h
+++ b/source/blender/usd/intern/usd_exporter_context.h
@@ -16,8 +16,8 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#ifndef __USD__USD_EXPORTER_CONTEXT_H__
-#define __USD__USD_EXPORTER_CONTEXT_H__
+#ifndef __USD_EXPORTER_CONTEXT_H__
+#define __USD_EXPORTER_CONTEXT_H__
#include "usd.h"
@@ -41,4 +41,4 @@ struct USDExporterContext {
} // namespace USD
-#endif /* __USD__USD_EXPORTER_CONTEXT_H__ */
+#endif /* __USD_EXPORTER_CONTEXT_H__ */
diff --git a/source/blender/usd/intern/usd_hierarchy_iterator.h b/source/blender/usd/intern/usd_hierarchy_iterator.h
index a937df8f15b..90c82c6e551 100644
--- a/source/blender/usd/intern/usd_hierarchy_iterator.h
+++ b/source/blender/usd/intern/usd_hierarchy_iterator.h
@@ -16,8 +16,8 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#ifndef __USD__USD_HIERARCHY_ITERATOR_H__
-#define __USD__USD_HIERARCHY_ITERATOR_H__
+#ifndef __USD_HIERARCHY_ITERATOR_H__
+#define __USD_HIERARCHY_ITERATOR_H__
#include "abstract_hierarchy_iterator.h"
#include "usd_exporter_context.h"
@@ -68,4 +68,4 @@ class USDHierarchyIterator : public AbstractHierarchyIterator {
} // namespace USD
-#endif /* __USD__USD_HIERARCHY_ITERATOR_H__ */
+#endif /* __USD_HIERARCHY_ITERATOR_H__ */
diff --git a/source/blender/usd/intern/usd_writer_abstract.h b/source/blender/usd/intern/usd_writer_abstract.h
index cea4685c806..8f727638704 100644
--- a/source/blender/usd/intern/usd_writer_abstract.h
+++ b/source/blender/usd/intern/usd_writer_abstract.h
@@ -16,8 +16,8 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#ifndef __USD__USD_WRITER_ABSTRACT_H__
-#define __USD__USD_WRITER_ABSTRACT_H__
+#ifndef __USD_WRITER_ABSTRACT_H__
+#define __USD_WRITER_ABSTRACT_H__
#include "usd_exporter_context.h"
#include "abstract_hierarchy_iterator.h"
@@ -75,4 +75,4 @@ class USDAbstractWriter : public AbstractHierarchyWriter {
} // namespace USD
-#endif /* __USD__USD_WRITER_ABSTRACT_H__ */
+#endif /* __USD_WRITER_ABSTRACT_H__ */
diff --git a/source/blender/usd/intern/usd_writer_camera.h b/source/blender/usd/intern/usd_writer_camera.h
index 86b5ed464b0..971264ef11e 100644
--- a/source/blender/usd/intern/usd_writer_camera.h
+++ b/source/blender/usd/intern/usd_writer_camera.h
@@ -16,8 +16,8 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#ifndef __USD__USD_WRITER_CAMERA_H__
-#define __USD__USD_WRITER_CAMERA_H__
+#ifndef __USD_WRITER_CAMERA_H__
+#define __USD_WRITER_CAMERA_H__
#include "usd_writer_abstract.h"
@@ -35,4 +35,4 @@ class USDCameraWriter : public USDAbstractWriter {
} // namespace USD
-#endif /* __USD__USD_WRITER_CAMERA_H__ */
+#endif /* __USD_WRITER_CAMERA_H__ */
diff --git a/source/blender/usd/intern/usd_writer_hair.h b/source/blender/usd/intern/usd_writer_hair.h
index ccb5af76099..1e882fa1654 100644
--- a/source/blender/usd/intern/usd_writer_hair.h
+++ b/source/blender/usd/intern/usd_writer_hair.h
@@ -16,8 +16,8 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#ifndef __USD__USD_WRITER_HAIR_H__
-#define __USD__USD_WRITER_HAIR_H__
+#ifndef __USD_WRITER_HAIR_H__
+#define __USD_WRITER_HAIR_H__
#include "usd_writer_abstract.h"
@@ -35,4 +35,4 @@ class USDHairWriter : public USDAbstractWriter {
} // namespace USD
-#endif /* __USD__USD_WRITER_HAIR_H__ */
+#endif /* __USD_WRITER_HAIR_H__ */
diff --git a/source/blender/usd/intern/usd_writer_light.h b/source/blender/usd/intern/usd_writer_light.h
index 3813412c330..349c034b6bc 100644
--- a/source/blender/usd/intern/usd_writer_light.h
+++ b/source/blender/usd/intern/usd_writer_light.h
@@ -16,8 +16,8 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#ifndef __USD__USD_WRITER_LIGHT_H__
-#define __USD__USD_WRITER_LIGHT_H__
+#ifndef __USD_WRITER_LIGHT_H__
+#define __USD_WRITER_LIGHT_H__
#include "usd_writer_abstract.h"
@@ -34,4 +34,4 @@ class USDLightWriter : public USDAbstractWriter {
} // namespace USD
-#endif /* __USD__USD_WRITER_LIGHT_H__ */
+#endif /* __USD_WRITER_LIGHT_H__ */
diff --git a/source/blender/usd/intern/usd_writer_mesh.h b/source/blender/usd/intern/usd_writer_mesh.h
index 0f03c8d20ae..56738e9747d 100644
--- a/source/blender/usd/intern/usd_writer_mesh.h
+++ b/source/blender/usd/intern/usd_writer_mesh.h
@@ -16,8 +16,8 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#ifndef __USD__USD_WRITER_MESH_H__
-#define __USD__USD_WRITER_MESH_H__
+#ifndef __USD_WRITER_MESH_H__
+#define __USD_WRITER_MESH_H__
#include "usd_writer_abstract.h"
@@ -63,4 +63,4 @@ class USDMeshWriter : public USDGenericMeshWriter {
} // namespace USD
-#endif /* __USD__USD_WRITER_MESH_H__ */
+#endif /* __USD_WRITER_MESH_H__ */
diff --git a/source/blender/usd/intern/usd_writer_transform.h b/source/blender/usd/intern/usd_writer_transform.h
index fb591998e6a..52c4a657f33 100644
--- a/source/blender/usd/intern/usd_writer_transform.h
+++ b/source/blender/usd/intern/usd_writer_transform.h
@@ -16,8 +16,8 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#ifndef __USD__USD_WRITER_TRANSFORM_H__
-#define __USD__USD_WRITER_TRANSFORM_H__
+#ifndef __USD_WRITER_TRANSFORM_H__
+#define __USD_WRITER_TRANSFORM_H__
#include "usd_writer_abstract.h"
@@ -39,4 +39,4 @@ class USDTransformWriter : public USDAbstractWriter {
} // namespace USD
-#endif /* __USD__USD_WRITER_TRANSFORM_H__ */
+#endif /* __USD_WRITER_TRANSFORM_H__ */
diff --git a/source/blender/usd/usd.h b/source/blender/usd/usd.h
index 412a51b8061..1a6f5819e21 100644
--- a/source/blender/usd/usd.h
+++ b/source/blender/usd/usd.h
@@ -17,8 +17,8 @@
* All rights reserved.
*/
-#ifndef __BLENDER_USD_H__
-#define __BLENDER_USD_H__
+#ifndef __USD_H__
+#define __USD_H__
#ifdef __cplusplus
extern "C" {
@@ -59,4 +59,4 @@ bool USD_export(struct bContext *C,
}
#endif
-#endif /* __BLENDER_USD_H__ */
+#endif /* __USD_H__ */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 01f80ab9297..4117c036dcb 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2265,9 +2265,18 @@ static int wm_handler_operator_call(bContext *C,
bool use_last_properties = true;
PointerRNA tool_properties = {0};
- bToolRef *keymap_tool = ((handler_base->type == WM_HANDLER_TYPE_KEYMAP) ?
- ((wmEventHandler_Keymap *)handler_base)->keymap_tool :
- NULL);
+ bToolRef *keymap_tool = NULL;
+ if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) {
+ keymap_tool = ((wmEventHandler_Keymap *)handler_base)->keymap_tool;
+ }
+ else if (handler_base->type == WM_HANDLER_TYPE_GIZMO) {
+ wmGizmoMap *gizmo_map = ((wmEventHandler_Gizmo *)handler_base)->gizmo_map;
+ wmGizmo *gz = wm_gizmomap_highlight_get(gizmo_map);
+ if (gz && (gz->flag & WM_GIZMO_OPERATOR_TOOL_INIT)) {
+ keymap_tool = WM_toolsystem_ref_from_context(C);
+ }
+ }
+
const bool is_tool = (keymap_tool != NULL);
const bool use_tool_properties = is_tool;
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index a116cfcef19..e19bc01d005 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -1050,7 +1050,7 @@ setup_liblinks(blender)
# USD registry.
# USD requires a set of JSON files that define the standard schemas. These
# files are required at runtime.
-if (WITH_USD)
+if(WITH_USD)
add_definitions(-DWITH_USD)
install(DIRECTORY
${LIBDIR}/usd/lib/usd
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 4cf0d6d40f2..5c6c1570152 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -115,13 +115,14 @@ void main_python_exit(void);
#endif
#ifdef WITH_USD
-/* Workaround to make it possible to pass a path at runtime to USD.
+/**
+ * Workaround to make it possible to pass a path at runtime to USD.
*
* USD requires some JSON files, and it uses a static constructor to determine the possible
- * filesystem paths to find those files. This made it impossible for Blender to pass a path to the
+ * file-system paths to find those files. This made it impossible for Blender to pass a path to the
* USD library at runtime, as the constructor would run before Blender's main() function. We have
* patched USD (see usd.diff) to avoid that particular static constructor, and have an
- * initialisation function instead.
+ * initialization function instead.
*
* This function is implemented in the USD source code, pxr/base/lib/plug/initConfig.cpp.
*/