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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2020-09-29 17:02:40 +0300
committerJacques Lucke <jacques@blender.org>2020-09-29 17:03:30 +0300
commit5845c06a63a6b96f038f5a46d538b0f9737102e9 (patch)
tree9a2bf0a1e90e6e37c60fcbf357c64874f258ab86
parente12767a0352a9e113892b4a07c6c8446d3ff361f (diff)
Volumes: new Mesh to Volume modifier
This modifier can only be added to Volume objects. It takes a mesh as input and generates a "density" grid near the surface or in the enclosed volume. Ref T73201. Reviewers: brecht Differential Revision: https://developer.blender.org/D9032
-rw-r--r--source/blender/blenkernel/BKE_volume.h12
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h34
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c77
-rw-r--r--source/blender/modifiers/CMakeLists.txt15
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h1
-rw-r--r--source/blender/modifiers/intern/MOD_mesh_to_volume.cc306
-rw-r--r--source/blender/modifiers/intern/MOD_util.c1
8 files changed, 447 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h
index b3437454f31..4481c1b4332 100644
--- a/source/blender/blenkernel/BKE_volume.h
+++ b/source/blender/blenkernel/BKE_volume.h
@@ -157,4 +157,16 @@ openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const struct Volume
openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *volume,
struct VolumeGrid *grid,
const bool clear);
+
+template<typename GridType>
+typename GridType::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *volume,
+ struct VolumeGrid *grid,
+ const bool clear)
+{
+ openvdb::GridBase::Ptr openvdb_grid = BKE_volume_grid_openvdb_for_write(volume, grid, clear);
+ BLI_assert(openvdb_grid->isType<GridType>());
+ typename GridType::Ptr typed_openvdb_grid = openvdb::gridPtrCast<GridType>(openvdb_grid);
+ return typed_openvdb_grid;
+}
+
#endif
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index c0716388f28..7218e75a404 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -95,6 +95,7 @@ typedef enum ModifierType {
eModifierType_Weld = 55,
eModifierType_Fluid = 56,
eModifierType_Simulation = 57,
+ eModifierType_MeshToVolume = 58,
NUM_MODIFIER_TYPES,
} ModifierType;
@@ -2208,6 +2209,39 @@ typedef struct SimulationModifierData {
char *data_path;
} SimulationModifierData;
+typedef struct MeshToVolumeModifierData {
+ ModifierData modifier;
+
+ /** This is the object that is supposed to be converted to a volume. */
+ struct Object *object;
+
+ /** MeshToVolumeModifierResolutionMode */
+ int resolution_mode;
+ /** Size of a voxel in object space. */
+ float voxel_size;
+ /** The desired amount of voxels along one axis. The actual amount of voxels might be slightly
+ * different. */
+ int voxel_amount;
+
+ /** If true, every cell in the enclosed volume gets a density. Otherwise, the interior_band_width
+ * is used. */
+ char fill_volume;
+ char _pad1[3];
+
+ /** Band widths are in object space. */
+ float interior_band_width;
+ float exterior_band_width;
+
+ float density;
+ char _pad2[4];
+} MeshToVolumeModifierData;
+
+/* MeshToVolumeModifierData->resolution_mode */
+typedef enum MeshToVolumeModifierResolutionMode {
+ MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT = 0,
+ MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE = 1,
+} MeshToVolumeModifierResolutionMode;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 10c122171e4..cfd87f14d48 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -389,6 +389,7 @@ extern StructRNA RNA_MaterialSlot;
extern StructRNA RNA_Menu;
extern StructRNA RNA_Mesh;
extern StructRNA RNA_MeshCacheModifier;
+extern StructRNA RNA_MeshToVolumeModifier;
extern StructRNA RNA_MeshColor;
extern StructRNA RNA_MeshDeformModifier;
extern StructRNA RNA_MeshEdge;
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 0e83ee150d6..b433c938bd6 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -193,6 +193,11 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
ICON_MOD_WIREFRAME,
"Wireframe",
"Convert faces into thickened edges"},
+ {eModifierType_MeshToVolume,
+ "MESH_TO_VOLUME",
+ ICON_VOLUME_DATA,
+ "Mesh to Volume",
+ ""}, /* TODO: Use correct icon. */
{0, "", 0, N_("Deform"), ""},
{eModifierType_Armature,
"ARMATURE",
@@ -6973,6 +6978,77 @@ static void rna_def_modifier_simulation(BlenderRNA *brna)
}
# endif
+static void rna_def_modifier_mesh_to_volume(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem resolution_mode_items[] = {
+ {MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT,
+ "VOXEL_AMOUNT",
+ 0,
+ "Voxel Amount",
+ "Desired number of voxels along one axis"},
+ {MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE,
+ "VOXEL_SIZE",
+ 0,
+ "Voxel Size",
+ "Desired voxel side length"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ srna = RNA_def_struct(brna, "MeshToVolumeModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Mesh to Volume Modifier", "");
+ RNA_def_struct_sdna(srna, "MeshToVolumeModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_VOLUME_DATA); /* TODO: Use correct icon. */
+
+ RNA_define_lib_overridable(true);
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ prop = RNA_def_property(srna, "resolution_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, resolution_mode_items);
+ RNA_def_property_ui_text(
+ prop, "Resolution Mode", "Mode for how the desired voxel size is specified");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "voxel_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(
+ prop, "Voxel Size", "Smaller values result in a higher resolution output");
+ RNA_def_property_range(prop, 0.1, FLT_MAX);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "voxel_amount", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Voxel Amount", "Approximate number of voxels along one axis");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "fill_volume", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(
+ prop, "Fill Volume", "Initialize the density grid in every cell inside the enclosed volume");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "interior_band_width", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Interior Band Width", "Width of the volume inside of the mesh");
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "exterior_band_width", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Exterior Band Width", "Width of the volume outside of the mesh");
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Density", "Density of the new volume");
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
+}
+
void RNA_def_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -7104,6 +7180,7 @@ void RNA_def_modifier(BlenderRNA *brna)
# ifdef WITH_PARTICLE_NODES
rna_def_modifier_simulation(brna);
# endif
+ rna_def_modifier_mesh_to_volume(brna);
}
#endif
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 8425d9bf569..3bc8a23184b 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -67,6 +67,7 @@ set(SRC
intern/MOD_laplaciansmooth.c
intern/MOD_lattice.c
intern/MOD_mask.cc
+ intern/MOD_mesh_to_volume.cc
intern/MOD_meshcache.c
intern/MOD_meshcache_mdd.c
intern/MOD_meshcache_pc2.c
@@ -177,6 +178,20 @@ if(WITH_GMP)
add_definitions(-DWITH_GMP)
endif()
+if(WITH_OPENVDB)
+ list(APPEND INC
+ ../../../intern/openvdb
+ )
+ list(APPEND INC_SYS
+ ${OPENVDB_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ bf_intern_openvdb
+ ${OPENVDB_LIBRARIES}
+ )
+ add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
+endif()
+
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_PARTICLE_NODES)
add_definitions(-DWITH_HAIR_NODES)
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index b011abf336d..e12f91ff99b 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -86,6 +86,7 @@ extern ModifierTypeInfo modifierType_MeshSequenceCache;
extern ModifierTypeInfo modifierType_SurfaceDeform;
extern ModifierTypeInfo modifierType_WeightedNormal;
extern ModifierTypeInfo modifierType_Simulation;
+extern ModifierTypeInfo modifierType_MeshToVolume;
/* MOD_util.c */
void modifier_type_init(ModifierTypeInfo *types[]);
diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
new file mode 100644
index 00000000000..4ec8e8fc44e
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
@@ -0,0 +1,306 @@
+/*
+ * 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 modifiers
+ */
+
+#include <vector>
+
+#include "BKE_lib_query.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_volume.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_volume_types.h"
+
+#include "DEG_depsgraph_build.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "BLO_read_write.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_ui_common.h"
+
+#include "BLI_float4x4.hh"
+#include "BLI_index_range.hh"
+#include "BLI_span.hh"
+
+#include "RNA_access.h"
+
+#ifdef WITH_OPENVDB
+# include <openvdb/openvdb.h>
+# include <openvdb/tools/MeshToVolume.h>
+#endif
+
+#ifdef WITH_OPENVDB
+namespace blender {
+/* This class follows the MeshDataAdapter interface from openvdb. */
+class OpenVDBMeshAdapter {
+ private:
+ Span<MVert> vertices_;
+ Span<MLoop> loops_;
+ Span<MLoopTri> looptris_;
+ float4x4 transform_;
+
+ public:
+ OpenVDBMeshAdapter(Mesh &mesh, float4x4 transform)
+ : vertices_(mesh.mvert, mesh.totvert),
+ loops_(mesh.mloop, mesh.totloop),
+ transform_(transform)
+ {
+ const MLoopTri *looptries = BKE_mesh_runtime_looptri_ensure(&mesh);
+ const int looptries_len = BKE_mesh_runtime_looptri_len(&mesh);
+ looptris_ = Span(looptries, looptries_len);
+ }
+
+ size_t polygonCount() const
+ {
+ return static_cast<size_t>(looptris_.size());
+ }
+
+ size_t pointCount() const
+ {
+ return static_cast<size_t>(vertices_.size());
+ }
+
+ size_t vertexCount(size_t UNUSED(polygon_index)) const
+ {
+ /* All polygons are triangles. */
+ return 3;
+ }
+
+ void getIndexSpacePoint(size_t polygon_index, size_t vertex_index, openvdb::Vec3d &pos) const
+ {
+ const MLoopTri &looptri = looptris_[polygon_index];
+ const MVert &vertex = vertices_[loops_[looptri.tri[vertex_index]].v];
+ const float3 transformed_co = transform_ * float3(vertex.co);
+ pos = &transformed_co.x;
+ }
+};
+} // namespace blender
+#endif
+
+static void initData(ModifierData *md)
+{
+ MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
+ mvmd->object = NULL;
+ mvmd->resolution_mode = MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT;
+ mvmd->voxel_size = 0.1f;
+ mvmd->voxel_amount = 32;
+ mvmd->fill_volume = true;
+ mvmd->interior_band_width = 0.1f;
+ mvmd->exterior_band_width = 0.1f;
+ mvmd->density = 1.0f;
+}
+
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
+{
+ MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
+ DEG_add_modifier_to_transform_relation(ctx->node, "Mesh to Volume Modifier");
+ if (mvmd->object) {
+ DEG_add_object_relation(
+ ctx->node, mvmd->object, DEG_OB_COMP_GEOMETRY, "Mesh to Volume Modifier");
+ DEG_add_object_relation(
+ ctx->node, mvmd->object, DEG_OB_COMP_TRANSFORM, "Mesh to Volume Modifier");
+ }
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
+{
+ MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
+ walk(userData, ob, &mvmd->object, IDWALK_CB_NOP);
+}
+
+static void panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
+ MeshToVolumeModifierData *mvmd = static_cast<MeshToVolumeModifierData *>(ptr->data);
+
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+
+ uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "density", 0, NULL, ICON_NONE);
+
+ {
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "fill_volume", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "exterior_band_width", 0, NULL, ICON_NONE);
+
+ uiLayout *subcol = uiLayoutColumn(col, false);
+ uiLayoutSetEnabled(subcol, !mvmd->fill_volume);
+ uiItemR(subcol, ptr, "interior_band_width", 0, NULL, ICON_NONE);
+ }
+ {
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiItemR(col, ptr, "resolution_mode", 0, NULL, ICON_NONE);
+ if (mvmd->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) {
+ uiItemR(col, ptr, "voxel_amount", 0, NULL, ICON_NONE);
+ }
+ else {
+ uiItemR(col, ptr, "voxel_size", 0, NULL, ICON_NONE);
+ }
+ }
+
+ modifier_panel_end(layout, ptr);
+}
+
+static void panelRegister(ARegionType *region_type)
+{
+ modifier_panel_register(region_type, eModifierType_MeshToVolume, panel_draw);
+}
+
+static float compute_voxel_size(const MeshToVolumeModifierData *mvmd,
+ const blender::float4x4 &transform)
+{
+ using namespace blender;
+ if (mvmd->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE) {
+ return MAX2(0.0001, mvmd->voxel_size);
+ }
+
+ /* Compute the voxel size based on the desired number of voxels and the approximated bounding box
+ * of the volume. */
+ const BoundBox *bb = BKE_object_boundbox_get(mvmd->object);
+ const float3 x_axis = float3(bb->vec[4]) - float3(bb->vec[0]);
+ const float3 y_axis = float3(bb->vec[3]) - float3(bb->vec[0]);
+ const float3 z_axis = float3(bb->vec[1]) - float3(bb->vec[0]);
+ const float max_dimension = std::max({(transform.ref_3x3() * x_axis).length(),
+ (transform.ref_3x3() * y_axis).length(),
+ (transform.ref_3x3() * z_axis).length()});
+ const float approximate_volume_side_length = max_dimension + mvmd->exterior_band_width * 2.0f;
+ const float voxel_size = approximate_volume_side_length / MAX2(1, mvmd->voxel_amount);
+ return voxel_size;
+}
+
+static Volume *modifyVolume(ModifierData *md, const ModifierEvalContext *ctx, Volume *input_volume)
+{
+#ifdef WITH_OPENVDB
+ using namespace blender;
+
+ MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
+ Object *object_to_convert = mvmd->object;
+
+ if (object_to_convert == NULL) {
+ return input_volume;
+ }
+ Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_to_convert, false);
+ if (mesh == NULL) {
+ return input_volume;
+ }
+
+ const float4x4 mesh_to_own_object_space_transform = float4x4(ctx->object->imat) *
+ float4x4(object_to_convert->obmat);
+ const float voxel_size = compute_voxel_size(mvmd, mesh_to_own_object_space_transform);
+
+ float4x4 mesh_to_index_space_transform;
+ scale_m4_fl(mesh_to_index_space_transform.values, 1.0f / voxel_size);
+ mul_m4_m4_post(mesh_to_index_space_transform.values, mesh_to_own_object_space_transform.values);
+ /* Better align generated grid with the source mesh. */
+ add_v3_fl(mesh_to_index_space_transform.values[3], -0.5f);
+
+ OpenVDBMeshAdapter mesh_adapter{*mesh, mesh_to_index_space_transform};
+
+ /* Convert the bandwidths from object in index space. */
+ const float exterior_band_width = MAX2(0.001f, mvmd->exterior_band_width / voxel_size);
+ const float interior_band_width = MAX2(0.001f, mvmd->interior_band_width / voxel_size);
+
+ openvdb::FloatGrid::Ptr new_grid;
+ if (mvmd->fill_volume) {
+ /* Setting the interior bandwidth to FLT_MAX, will make it fill the entire volume. */
+ new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
+ mesh_adapter, {}, exterior_band_width, FLT_MAX);
+ }
+ else {
+ new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
+ mesh_adapter, {}, exterior_band_width, interior_band_width);
+ }
+
+ /* Create a new volume object and add the density grid. */
+ Volume *volume = BKE_volume_new_for_eval(input_volume);
+ VolumeGrid *c_density_grid = BKE_volume_grid_add(volume, "density", VOLUME_GRID_FLOAT);
+ openvdb::FloatGrid::Ptr density_grid = BKE_volume_grid_openvdb_for_write<openvdb::FloatGrid>(
+ volume, c_density_grid, false);
+
+ /* Merge the generated grid into the density grid. Should be cheap because density_grid has just
+ * been created as well. */
+ density_grid->merge(*new_grid);
+
+ /* Change transform so that the index space is correctly transformed to object space. */
+ density_grid->transform().postScale(voxel_size);
+
+ /* Give each grid cell a fixed density for now. */
+ openvdb::tools::foreach (
+ density_grid->beginValueOn(),
+ [&](const openvdb::FloatGrid::ValueOnIter &iter) { iter.setValue(mvmd->density); });
+
+ return volume;
+
+#else
+ UNUSED_VARS(md, ctx);
+ UNUSED_VARS(compute_voxel_size);
+ BKE_modifier_set_error(md, "Compiled without OpenVDB");
+ return input_volume;
+#endif
+}
+
+ModifierTypeInfo modifierType_MeshToVolume = {
+ /* name */ "Mesh to Volume",
+ /* structName */ "MeshToVolumeModifierData",
+ /* structSize */ sizeof(MeshToVolumeModifierData),
+ /* srna */ &RNA_MeshToVolumeModifier,
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ static_cast<ModifierTypeFlag>(0),
+ /* icon */ ICON_VOLUME_DATA, /* TODO: Use correct icon. */
+
+ /* copyData */ BKE_modifier_copydata_generic,
+
+ /* deformVerts */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* modifyMesh */ NULL,
+ /* modifyHair */ NULL,
+ /* modifyPointCloud */ NULL,
+ /* modifyVolume */ modifyVolume,
+
+ /* initData */ initData,
+ /* requiredDataMask */ NULL,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+ /* freeRuntimeData */ NULL,
+ /* panelRegister */ panelRegister,
+ /* blendWrite */ NULL,
+ /* blendRead */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index cc844e53603..75436435e97 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -343,5 +343,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(SurfaceDeform);
INIT_TYPE(WeightedNormal);
INIT_TYPE(Simulation);
+ INIT_TYPE(MeshToVolume);
#undef INIT_TYPE
}