[Bf-blender-cvs] [9cbc8740624] mesh-to-volume-modifier: support different modes of operation

Jacques Lucke noreply at git.blender.org
Thu Sep 24 15:32:35 CEST 2020


Commit: 9cbc8740624220f7de60248ec01ce0c05bfaba24
Author: Jacques Lucke
Date:   Thu Sep 24 15:32:27 2020 +0200
Branches: mesh-to-volume-modifier
https://developer.blender.org/rB9cbc8740624220f7de60248ec01ce0c05bfaba24

support different modes of operation

===================================================================

M	source/blender/makesdna/DNA_modifier_types.h
M	source/blender/makesrna/intern/rna_modifier.c
M	source/blender/modifiers/intern/MOD_mesh_to_volume.cc

===================================================================

diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index e8c48ef5972..69c010428c2 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -2212,13 +2212,43 @@ typedef struct SimulationModifierData {
 
 typedef struct MeshToVolumeModifierData {
   ModifierData modifier;
+
+  /** This is the object that is supposed to be converted to a volume. */
   struct Object *object;
+
+  /** MeshToVolumeModifierMode */
+  int mode;
+
+  /** 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_bandwidth
+   * is used. */
+  char fill_volume;
+  char _pad1[3];
+  /** Bandwidths are on object space. */
   float interior_bandwidth;
   float exterior_bandwidth;
   char _pad[4];
 } MeshToVolumeModifierData;
 
+/* MeshToVolumeModifierData->mode */
+typedef enum MeshToVolumeModifierMode {
+  MESH_TO_VOLUME_MODE_VOLUME = 0,
+  MESH_TO_VOLUME_MODE_SURFACE = 1,
+} MeshToVolumeModifierMode;
+
+/* 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/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index ebaab7d5c0d..94f9fd9bb49 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -7103,6 +7103,34 @@ static void rna_def_modifier_mesh_to_volume(BlenderRNA *brna)
   StructRNA *srna;
   PropertyRNA *prop;
 
+  static EnumPropertyItem mode_items[] = {
+      {MESH_TO_VOLUME_MODE_VOLUME,
+       "VOLUME",
+       0,
+       "Volume",
+       "Create a volume based on the volume that is enclosed by the mesh surface"},
+      {MESH_TO_VOLUME_MODE_SURFACE,
+       "SURFACE",
+       0,
+       "Surface",
+       "Create a volume based on the mesh surface"},
+      {0, NULL, 0, NULL, NULL},
+  };
+
+  static EnumPropertyItem resolution_mode_items[] = {
+      {MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT,
+       "VOXEL_AMOUNT",
+       0,
+       "Voxel Amount",
+       "Specify the desired number of voxels along one axis"},
+      {MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE,
+       "VOXEL_SIZE",
+       0,
+       "Voxel Size",
+       "Specify the 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");
@@ -7115,12 +7143,33 @@ static void rna_def_modifier_mesh_to_volume(BlenderRNA *brna)
   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, "mode", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_items(prop, mode_items);
+  RNA_def_property_ui_text(prop, "Mode", "Mode for the mesh to volume conversion");
+  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", "The smaller this number the higher the resolution of the 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", "The desired 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_bandwidth", PROP_FLOAT, PROP_NONE);
   RNA_def_property_ui_text(prop, "Interior Bandwidth", "Width of the volume inside of the mesh");
   RNA_def_property_range(prop, 0.0, FLT_MAX);
diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
index e41d1f9a291..d853d67f99c 100644
--- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
+++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc
@@ -23,6 +23,7 @@
 #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"
@@ -103,7 +104,11 @@ static void initData(ModifierData *md)
 {
   MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
   mvmd->object = NULL;
+  mvmd->mode = MESH_TO_VOLUME_MODE_VOLUME;
+  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_bandwidth = 1.0f;
   mvmd->exterior_bandwidth = 1.0f;
 }
@@ -133,14 +138,32 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
 
   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, "voxel_size", 0, NULL, ICON_NONE);
-  uiItemR(layout, ptr, "interior_bandwidth", 0, NULL, ICON_NONE);
-  uiItemR(layout, ptr, "exterior_bandwidth", 0, NULL, ICON_NONE);
+
+  uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
+  if (mvmd->mode == MESH_TO_VOLUME_MODE_VOLUME) {
+    uiItemR(layout, ptr, "fill_volume", 0, NULL, ICON_NONE);
+    uiItemR(layout, ptr, "exterior_bandwidth", 0, NULL, ICON_NONE);
+    if (!mvmd->fill_volume) {
+      uiItemR(layout, ptr, "interior_bandwidth", 0, NULL, ICON_NONE);
+    }
+  }
+  else if (mvmd->mode == MESH_TO_VOLUME_MODE_SURFACE) {
+    uiItemR(layout, ptr, "exterior_bandwidth", 0, "Bandwidth", ICON_NONE);
+  }
+
+  uiItemR(layout, ptr, "resolution_mode", 0, NULL, ICON_NONE);
+  if (mvmd->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) {
+    uiItemR(layout, ptr, "voxel_amount", 0, NULL, ICON_NONE);
+  }
+  else {
+    uiItemR(layout, ptr, "voxel_size", 0, NULL, ICON_NONE);
+  }
 
   modifier_panel_end(layout, ptr);
 }
@@ -150,6 +173,25 @@ 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);
+  }
+  BoundBox *bb = BKE_object_boundbox_get(mvmd->object);
+
+  float3 dimensions = float3(bb->vec[6]) - float3(bb->vec[0]);
+  const float3 transformed_dimensions = transform.ref_3x3() * dimensions;
+  const float max_dimension = std::max(
+      {transformed_dimensions.x, transformed_dimensions.y, transformed_dimensions.z});
+  const float approximate_volume_side_length = max_dimension + mvmd->exterior_bandwidth * 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
@@ -165,28 +207,46 @@ static Volume *modifyVolume(ModifierData *md, const ModifierEvalContext *ctx, Vo
   }
 
   Object *object_to_convert = mvmd->object;
-  Mesh *mesh = static_cast<Mesh *>(object_to_convert->data);
-  const float voxel_size = mvmd->voxel_size;
-  const float exterior_bandwidth = MAX2(0.001f, mvmd->exterior_bandwidth / voxel_size);
-  const float interior_bandwidth = MAX2(0.001f, mvmd->interior_bandwidth / voxel_size);
-  UNUSED_VARS(voxel_size);
+  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);
 
-  float4x4 transform;
-  scale_m4_fl(transform.values, 1.0f / voxel_size);
-  mul_m4_m4_post(transform.values, ctx->object->imat);
-  mul_m4_m4_post(transform.values, object_to_convert->obmat);
+  Mesh *mesh = static_cast<Mesh *>(object_to_convert->data);
+  OpenVDBMeshAdapter mesh_adapter{*mesh, mesh_to_index_space_transform};
 
-  OpenVDBMeshAdapter mesh_adapter{*mesh, transform};
+  openvdb::FloatGrid::Ptr new_grid;
 
-  openvdb::FloatGrid::Ptr new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
-      mesh_adapter, {}, exterior_bandwidth, interior_bandwidth);
+  const float exterior_bandwidth = MAX2(0.001f, mvmd->exterior_bandwidth / voxel_size);
+  const float interior_bandwidth = MAX2(0.001f, mvmd->interior_bandwidth / voxel_size);
+  if (mvmd->mode == MESH_TO_VOLUME_MODE_VOLUME) {
+    if (mvmd->fill_volume) {
+      new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
+          mesh_adapter, {}, exterior_bandwidth, FLT_MAX);
+    }
+    else {
+      n

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list