diff options
author | Jacques Lucke <jacques@blender.org> | 2020-10-19 13:11:38 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-10-19 13:12:44 +0300 |
commit | f7832b1583cd13bde182192bce358db3062a0547 (patch) | |
tree | ffde72d963ea62b239c6a57c928534823a22808d /source/blender | |
parent | bd15efefd2f2d3554364303a09b67198e39d7bcd (diff) |
Volumes: new Volume to Mesh modifier
This modifier is the opposite of the recently added Mesh to Volume modifier.
It converts the "surface" of a volume into a mesh. The "surface" is defined
by a threshold value. All voxels with a density higher than the threshold
are considered to be inside the volume, while all others will be outside.
By default, the resolution of the generated mesh depends on the voxel
size of the volume grid. The resolution can be customized. It should be
noted that a lower resolution might not make this modifier faster. This
is because we have to downsample the openvdb grid, which isn't a cheap
operation.
Converting a mesh to a volume and then back to a mesh is possible,
but it does require two separate mesh objects for now.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D9141
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 34 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_modifier.c | 89 | ||||
-rw-r--r-- | source/blender/modifiers/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/modifiers/MOD_modifiertypes.h | 1 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_util.c | 1 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_volume_to_mesh.cc | 343 |
8 files changed, 471 insertions, 2 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index fdea26ce730..0275f4dd587 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -22,9 +22,8 @@ * \ingroup bke */ -/* defines BLI_INLINE */ #include "BKE_mesh_types.h" -#include "BLI_compiler_compat.h" +#include "BLI_utildefines.h" struct BLI_Stack; struct BMEditMesh; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 7a13b9f4852..34d2c80dc5d 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -97,6 +97,7 @@ typedef enum ModifierType { eModifierType_Simulation = 57, eModifierType_MeshToVolume = 58, eModifierType_VolumeDisplace = 59, + eModifierType_VolumeToMesh = 60, NUM_MODIFIER_TYPES, } ModifierType; @@ -2275,6 +2276,39 @@ enum { MOD_VOLUME_DISPLACE_MAP_OBJECT = 2, }; +typedef struct VolumeToMeshModifierData { + ModifierData modifier; + + /** This is the volume object that is supposed to be converted to a mesh. */ + struct Object *object; + + float threshold; + float adaptivity; + + /** VolumeToMeshFlag */ + uint32_t flag; + + /** VolumeToMeshResolutionMode */ + int resolution_mode; + float voxel_size; + int voxel_amount; + + /** MAX_NAME */ + char grid_name[64]; +} VolumeToMeshModifierData; + +/** VolumeToMeshModifierData->resolution_mode */ +typedef enum VolumeToMeshResolutionMode { + VOLUME_TO_MESH_RESOLUTION_MODE_GRID = 0, + VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT = 1, + VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE = 2, +} VolumeToMeshResolutionMode; + +/** VolumeToMeshModifierData->flag */ +typedef enum VolumeToMeshFlag { + VOLUME_TO_MESH_USE_SMOOTH_SHADE = 1 << 0, +} VolumeToMeshFlag; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 0b882742839..8096c6d7d10 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -710,6 +710,7 @@ extern StructRNA RNA_ViewLayer; extern StructRNA RNA_ViewLayerEEVEE; extern StructRNA RNA_Volume; extern StructRNA RNA_VolumeDisplaceModifier; +extern StructRNA RNA_VolumeToMeshModifier; extern StructRNA RNA_VoronoiTexture; extern StructRNA RNA_WalkNavigation; extern StructRNA RNA_WarpModifier; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 0010e473924..48ea894aba1 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -198,6 +198,11 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { ICON_VOLUME_DATA, "Mesh to Volume", ""}, /* TODO: Use correct icon. */ + {eModifierType_VolumeToMesh, + "VOLUME_TO_MESH", + ICON_VOLUME_DATA, + "Volume to Mesh", + ""}, /* TODO: Use correct icon. */ {0, "", 0, N_("Deform"), ""}, {eModifierType_Armature, "ARMATURE", @@ -7133,6 +7138,89 @@ static void rna_def_modifier_volume_displace(BlenderRNA *brna) RNA_define_lib_overridable(false); } +static void rna_def_modifier_volume_to_mesh(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem resolution_mode_items[] = { + {VOLUME_TO_MESH_RESOLUTION_MODE_GRID, + "GRID", + 0, + "Grid", + "Use resolution of the volume grid"}, + {VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT, + "VOXEL_AMOUNT", + 0, + "Voxel Amount", + "Desired number of voxels along one axis"}, + {VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE, + "VOXEL_SIZE", + 0, + "Voxel Size", + "Desired voxel side length"}, + {0, NULL, 0, NULL, NULL}, + }; + + srna = RNA_def_struct(brna, "VolumeToMeshModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Volume to Mesh Modifier", ""); + RNA_def_struct_sdna(srna, "VolumeToMeshModifierData"); + 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, "threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text( + prop, "Threshold", "Voxels with a larger value are inside the generated mesh"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.001f, 1.0f, 0.1f, 5); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "adaptivity", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text( + prop, + "Adaptivity", + "Reduces the final face count by simplifying geometry where detail is not needed"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_smooth_shade", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", VOLUME_TO_MESH_USE_SMOOTH_SHADE); + RNA_def_property_ui_text( + prop, "Smooth Shading", "Output faces with smooth shading rather than flat shaded"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "grid_name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text( + prop, "Grid Name", "Grid in the volume object that is converted to a mesh"); + RNA_def_property_update(prop, 0, "rna_Modifier_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.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0, FLT_MAX, 0.01, 4); + 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"); + + RNA_define_lib_overridable(false); +} + void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -7266,6 +7354,7 @@ void RNA_def_modifier(BlenderRNA *brna) # endif rna_def_modifier_mesh_to_volume(brna); rna_def_modifier_volume_displace(brna); + rna_def_modifier_volume_to_mesh(brna); } #endif diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index f5786dc0701..754a7eefee7 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -102,6 +102,7 @@ set(SRC intern/MOD_uvproject.c intern/MOD_uvwarp.c intern/MOD_volume_displace.cc + intern/MOD_volume_to_mesh.cc intern/MOD_warp.c intern/MOD_wave.c intern/MOD_weighted_normal.c diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index 6dc50e1b47d..9c488780366 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -88,6 +88,7 @@ extern ModifierTypeInfo modifierType_WeightedNormal; extern ModifierTypeInfo modifierType_Simulation; extern ModifierTypeInfo modifierType_MeshToVolume; extern ModifierTypeInfo modifierType_VolumeDisplace; +extern ModifierTypeInfo modifierType_VolumeToMesh; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 275e8a626d5..e0802dc5fb4 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -345,5 +345,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(Simulation); INIT_TYPE(MeshToVolume); INIT_TYPE(VolumeDisplace); + INIT_TYPE(VolumeToMesh); #undef INIT_TYPE } diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc new file mode 100644 index 00000000000..ea292155d3c --- /dev/null +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -0,0 +1,343 @@ +/* + * 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.h" +#include "BKE_modifier.h" +#include "BKE_volume.h" + +#include "MOD_modifiertypes.h" +#include "MOD_ui_common.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_volume_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "RNA_access.h" + +#include "BLI_float4x4.hh" +#include "BLI_math_vector.h" +#include "BLI_span.hh" +#include "BLI_timeit.hh" + +#ifdef WITH_OPENVDB +# include <openvdb/tools/GridTransformer.h> +# include <openvdb/tools/VolumeToMesh.h> +#endif + +using blender::float3; +using blender::float4x4; +using blender::Span; + +static void initData(ModifierData *md) +{ + VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md); + vmmd->object = NULL; + vmmd->threshold = 0.1f; + strncpy(vmmd->grid_name, "density", MAX_NAME); + vmmd->adaptivity = 0.0f; + vmmd->resolution_mode = VOLUME_TO_MESH_RESOLUTION_MODE_GRID; + vmmd->voxel_amount = 32; + vmmd->voxel_size = 0.1f; + vmmd->flag = 0; +} + +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +{ + VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md); + DEG_add_modifier_to_transform_relation(ctx->node, "Volume to Mesh Modifier"); + if (vmmd->object) { + DEG_add_object_relation( + ctx->node, vmmd->object, DEG_OB_COMP_GEOMETRY, "Volume to Mesh Modifier"); + DEG_add_object_relation( + ctx->node, vmmd->object, DEG_OB_COMP_TRANSFORM, "Volume to Mesh Modifier"); + } +} + +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md); + walk(userData, ob, (ID **)&vmmd->object, IDWALK_CB_NOP); +} + +static void panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, NULL); + VolumeToMeshModifierData *vmmd = static_cast<VolumeToMeshModifierData *>(ptr->data); + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + + { + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "object", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "grid_name", 0, NULL, ICON_NONE); + } + + { + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "resolution_mode", 0, NULL, ICON_NONE); + if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT) { + uiItemR(col, ptr, "voxel_amount", 0, NULL, ICON_NONE); + } + else if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { + uiItemR(col, ptr, "voxel_size", 0, NULL, ICON_NONE); + } + } + + { + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "adaptivity", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_smooth_shade", 0, NULL, ICON_NONE); + } + + modifier_panel_end(layout, ptr); +} + +static void panelRegister(ARegionType *region_type) +{ + modifier_panel_register(region_type, eModifierType_VolumeToMesh, panel_draw); +} + +#ifdef WITH_OPENVDB + +struct VolumeToMeshOp { + const openvdb::GridBase &base_grid; + VolumeToMeshModifierData &vmmd; + const ModifierEvalContext &ctx; + std::vector<openvdb::Vec3s> verts; + std::vector<openvdb::Vec3I> tris; + std::vector<openvdb::Vec4I> quads; + + template<typename GridType> bool operator()() + { + if constexpr (std::is_scalar_v<typename GridType::ValueType>) { + this->generate_mesh_data<GridType>(); + return true; + } + else { + return false; + } + } + + template<typename GridType> void generate_mesh_data() + { + /* Make a new transform from the index space into the mesh object space. */ + openvdb::math::Transform::Ptr transform = this->base_grid.transform().copy(); + transform->postMult(openvdb::Mat4d((float *)vmmd.object->obmat)); + openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx.object->imat); + /* `imat` had floating point issues and wasn't affine. */ + imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1)); + transform->postMult(imat); + + /* Create a new grid with a different transform. The underlying tree is shared. */ + typename GridType::ConstPtr grid = openvdb::gridConstPtrCast<GridType>( + this->base_grid.copyGridReplacingTransform(transform)); + + if (this->vmmd.resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_GRID) { + this->grid_to_mesh(*grid); + return; + } + + const float resolution_factor = this->compute_resolution_factor(*grid); + typename GridType::Ptr temp_grid = this->create_grid_with_changed_resolution( + *grid, resolution_factor); + this->grid_to_mesh(*temp_grid); + } + + template<typename GridType> + typename GridType::Ptr create_grid_with_changed_resolution(const GridType &old_grid, + const float resolution_factor) + { + BLI_assert(resolution_factor > 0.0f); + + openvdb::Mat4R xform; + xform.setToScale(openvdb::Vec3d(resolution_factor)); + openvdb::tools::GridTransformer transformer{xform}; + + typename GridType::Ptr new_grid = GridType::create(); + transformer.transformGrid<openvdb::tools::BoxSampler>(old_grid, *new_grid); + new_grid->transform() = old_grid.transform(); + new_grid->transform().preScale(1.0f / resolution_factor); + return new_grid; + } + + float compute_resolution_factor(const openvdb::GridBase &grid) const + { + const openvdb::Vec3s voxel_size{grid.voxelSize()}; + const float current_voxel_size = std::max({voxel_size[0], voxel_size[1], voxel_size[2]}); + const float desired_voxel_size = this->compute_desired_voxel_size(grid); + return current_voxel_size / desired_voxel_size; + } + + float compute_desired_voxel_size(const openvdb::GridBase &grid) const + { + if (this->vmmd.resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { + return this->vmmd.voxel_size; + } + const openvdb::CoordBBox coord_bbox = base_grid.evalActiveVoxelBoundingBox(); + const openvdb::BBoxd bbox = grid.transform().indexToWorld(coord_bbox); + const float max_extent = bbox.extents()[bbox.maxExtent()]; + const float voxel_size = max_extent / this->vmmd.voxel_amount; + return voxel_size; + } + + template<typename GridType> void grid_to_mesh(const GridType &grid) + { + openvdb::tools::volumeToMesh( + grid, this->verts, this->tris, this->quads, this->vmmd.threshold, this->vmmd.adaptivity); + } +}; + +static Mesh *new_mesh_from_openvdb_data(Span<openvdb::Vec3s> verts, + Span<openvdb::Vec3I> tris, + Span<openvdb::Vec4I> quads) +{ + const int tot_loops = 3 * tris.size() + 4 * quads.size(); + const int tot_polys = tris.size() + quads.size(); + + Mesh *mesh = BKE_mesh_new_nomain(verts.size(), 0, 0, tot_loops, tot_polys); + + /* Write vertices. */ + for (const int i : verts.index_range()) { + const blender::float3 co = blender::float3(verts[i].asV()); + copy_v3_v3(mesh->mvert[i].co, co); + } + + /* Write triangles. */ + for (const int i : tris.index_range()) { + mesh->mpoly[i].loopstart = 3 * i; + mesh->mpoly[i].totloop = 3; + for (int j = 0; j < 3; j++) { + mesh->mloop[3 * i + j].v = tris[i][j]; + } + } + + /* Write quads. */ + const int poly_offset = tris.size(); + const int loop_offset = tris.size() * 3; + for (const int i : quads.index_range()) { + mesh->mpoly[poly_offset + i].loopstart = loop_offset + 4 * i; + mesh->mpoly[poly_offset + i].totloop = 4; + for (int j = 0; j < 4; j++) { + mesh->mloop[loop_offset + 4 * i + j].v = quads[i][j]; + } + } + + BKE_mesh_calc_edges(mesh, false, false); + BKE_mesh_calc_normals(mesh); + return mesh; +} +#endif + +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *input_mesh) +{ +#ifdef WITH_OPENVDB + VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md); + if (vmmd->object == nullptr) { + return input_mesh; + } + if (vmmd->object->type != OB_VOLUME) { + return input_mesh; + } + if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE && + vmmd->voxel_size == 0.0f) { + return input_mesh; + } + if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT && + vmmd->voxel_amount == 0) { + return input_mesh; + } + + Volume *volume = static_cast<Volume *>(vmmd->object->data); + + VolumeGrid *volume_grid = BKE_volume_grid_find(volume, vmmd->grid_name); + if (volume_grid == nullptr) { + BKE_modifier_set_error(md, "Cannot find '%s' grid", vmmd->grid_name); + return input_mesh; + } + + const openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); + + const VolumeGridType grid_type = BKE_volume_grid_type(volume_grid); + VolumeToMeshOp to_mesh_op{*grid, *vmmd, *ctx}; + if (!BKE_volume_grid_type_operation(grid_type, to_mesh_op)) { + BKE_modifier_set_error(md, "Expected a scalar grid"); + return input_mesh; + } + + Mesh *mesh = new_mesh_from_openvdb_data(to_mesh_op.verts, to_mesh_op.tris, to_mesh_op.quads); + BKE_mesh_copy_settings(mesh, input_mesh); + if (vmmd->flag & VOLUME_TO_MESH_USE_SMOOTH_SHADE) { + BKE_mesh_smooth_flag_set(mesh, true); + } + return mesh; +#else + UNUSED_VARS(md, ctx); + BKE_modifier_set_error(md, "Compiled without OpenVDB"); + return input_mesh; +#endif +} + +ModifierTypeInfo modifierType_VolumeToMesh = { + /* name */ "Volume to Mesh", + /* structName */ "VolumeToMeshModifierData", + /* structSize */ sizeof(VolumeToMeshModifierData), + /* srna */ &RNA_VolumeToMeshModifier, + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh, + /* icon */ ICON_VOLUME_DATA, /* TODO: Use correct icon. */ + + /* copyData */ BKE_modifier_copydata_generic, + + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, + + /* initData */ initData, + /* requiredDataMask */ NULL, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, + /* panelRegister */ panelRegister, + /* blendWrite */ NULL, + /* blendRead */ NULL, +}; |