Blender  V3.3
MOD_volume_to_mesh.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <vector>
8 
9 #include "BKE_lib_query.h"
10 #include "BKE_mesh.h"
11 #include "BKE_modifier.h"
12 #include "BKE_volume.h"
13 #include "BKE_volume_to_mesh.hh"
14 
15 #include "BLT_translation.h"
16 
17 #include "MOD_modifiertypes.h"
18 #include "MOD_ui_common.h"
19 
20 #include "DNA_mesh_types.h"
21 #include "DNA_meshdata_types.h"
22 #include "DNA_modifier_types.h"
23 #include "DNA_object_types.h"
24 #include "DNA_screen_types.h"
25 #include "DNA_volume_types.h"
26 
27 #include "UI_interface.h"
28 #include "UI_resources.h"
29 
30 #include "RNA_access.h"
31 #include "RNA_prototypes.h"
32 
33 #include "BLI_float4x4.hh"
34 #include "BLI_math_vector.h"
35 #include "BLI_span.hh"
36 #include "BLI_timeit.hh"
37 
38 #include "DEG_depsgraph_query.h"
39 
40 #ifdef WITH_OPENVDB
41 # include <openvdb/tools/GridTransformer.h>
42 # include <openvdb/tools/VolumeToMesh.h>
43 #endif
44 
45 using blender::float3;
46 using blender::float4x4;
47 using blender::Span;
48 
49 static void initData(ModifierData *md)
50 {
51  VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md);
52  vmmd->object = nullptr;
53  vmmd->threshold = 0.1f;
54  strncpy(vmmd->grid_name, "density", MAX_NAME);
55  vmmd->adaptivity = 0.0f;
57  vmmd->voxel_amount = 32;
58  vmmd->voxel_size = 0.1f;
59  vmmd->flag = 0;
60 }
61 
63 {
64  VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md);
65  DEG_add_modifier_to_transform_relation(ctx->node, "Volume to Mesh Modifier");
66  if (vmmd->object) {
68  ctx->node, vmmd->object, DEG_OB_COMP_GEOMETRY, "Volume to Mesh Modifier");
70  ctx->node, vmmd->object, DEG_OB_COMP_TRANSFORM, "Volume to Mesh Modifier");
71  }
72 }
73 
74 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
75 {
76  VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md);
77  walk(userData, ob, (ID **)&vmmd->object, IDWALK_CB_NOP);
78 }
79 
80 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
81 {
82  uiLayout *layout = panel->layout;
83 
86 
87  uiLayoutSetPropSep(layout, true);
88 
89  {
90  uiLayout *col = uiLayoutColumn(layout, false);
91  uiItemR(col, ptr, "object", 0, nullptr, ICON_NONE);
92  uiItemR(col, ptr, "grid_name", 0, nullptr, ICON_NONE);
93  }
94 
95  {
96  uiLayout *col = uiLayoutColumn(layout, false);
97  uiItemR(col, ptr, "resolution_mode", 0, nullptr, ICON_NONE);
99  uiItemR(col, ptr, "voxel_amount", 0, nullptr, ICON_NONE);
100  }
102  uiItemR(col, ptr, "voxel_size", 0, nullptr, ICON_NONE);
103  }
104  }
105 
106  {
107  uiLayout *col = uiLayoutColumn(layout, false);
108  uiItemR(col, ptr, "threshold", 0, nullptr, ICON_NONE);
109  uiItemR(col, ptr, "adaptivity", 0, nullptr, ICON_NONE);
110  uiItemR(col, ptr, "use_smooth_shade", 0, nullptr, ICON_NONE);
111  }
112 
113  modifier_panel_end(layout, ptr);
114 }
115 
116 static void panelRegister(ARegionType *region_type)
117 {
119 }
120 
121 static Mesh *create_empty_mesh(const Mesh *input_mesh)
122 {
123  Mesh *new_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0);
124  BKE_mesh_copy_parameters_for_eval(new_mesh, input_mesh);
125  return new_mesh;
126 }
127 
128 static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *input_mesh)
129 {
130 #ifdef WITH_OPENVDB
131  VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md);
132  if (vmmd->object == nullptr) {
133  return create_empty_mesh(input_mesh);
134  }
135  if (vmmd->object->type != OB_VOLUME) {
136  return create_empty_mesh(input_mesh);
137  }
139  vmmd->voxel_size == 0.0f) {
140  return create_empty_mesh(input_mesh);
141  }
143  vmmd->voxel_amount == 0) {
144  return create_empty_mesh(input_mesh);
145  }
146 
147  const Volume *volume = static_cast<Volume *>(vmmd->object->data);
148 
149  BKE_volume_load(volume, DEG_get_bmain(ctx->depsgraph));
150  const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, vmmd->grid_name);
151  if (volume_grid == nullptr) {
152  BKE_modifier_set_error(ctx->object, md, "Cannot find '%s' grid", vmmd->grid_name);
153  return create_empty_mesh(input_mesh);
154  }
155 
156  const openvdb::GridBase::ConstPtr local_grid = BKE_volume_grid_openvdb_for_read(volume,
157  volume_grid);
158 
159  openvdb::math::Transform::Ptr transform = local_grid->transform().copy();
160  transform->postMult(openvdb::Mat4d(((float *)vmmd->object->obmat)));
161  openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx->object->imat);
162  /* `imat` had floating point issues and wasn't affine. */
163  imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1));
164  transform->postMult(imat);
165 
166  /* Create a temporary transformed grid. The underlying tree is shared. */
167  openvdb::GridBase::ConstPtr transformed_grid = local_grid->copyGridReplacingTransform(transform);
168 
170  resolution.mode = (VolumeToMeshResolutionMode)vmmd->resolution_mode;
172  resolution.settings.voxel_amount = vmmd->voxel_amount;
173  }
175  resolution.settings.voxel_size = vmmd->voxel_size;
176  }
177 
178  Mesh *mesh = blender::bke::volume_to_mesh(
179  *transformed_grid, resolution, vmmd->threshold, vmmd->adaptivity);
180  if (mesh == nullptr) {
181  BKE_modifier_set_error(ctx->object, md, "Could not generate mesh from grid");
182  return create_empty_mesh(input_mesh);
183  }
184 
188  }
189  return mesh;
190 #else
191  UNUSED_VARS(md);
192  BKE_modifier_set_error(ctx->object, md, "Compiled without OpenVDB");
193  return create_empty_mesh(input_mesh);
194 #endif
195 }
196 
198  /* name */ N_("Volume to Mesh"),
199  /* structName */ "VolumeToMeshModifierData",
200  /* structSize */ sizeof(VolumeToMeshModifierData),
201  /* srna */ &RNA_VolumeToMeshModifier,
203  /* flags */ eModifierTypeFlag_AcceptsMesh,
204  /* icon */ ICON_VOLUME_DATA, /* TODO: Use correct icon. */
205 
206  /* copyData */ BKE_modifier_copydata_generic,
207 
208  /* deformVerts */ nullptr,
209  /* deformMatrices */ nullptr,
210  /* deformVertsEM */ nullptr,
211  /* deformMatricesEM */ nullptr,
212  /* modifyMesh */ modifyMesh,
213  /* modifyGeometrySet */ nullptr,
214 
215  /* initData */ initData,
216  /* requiredDataMask */ nullptr,
217  /* freeData */ nullptr,
218  /* isDisabled */ nullptr,
219  /* updateDepsgraph */ updateDepsgraph,
220  /* dependsOnTime */ nullptr,
221  /* dependsOnNormals */ nullptr,
222  /* foreachIDLink */ foreachIDLink,
223  /* foreachTexLink */ nullptr,
224  /* freeRuntimeData */ nullptr,
225  /* panelRegister */ panelRegister,
226  /* blendWrite */ nullptr,
227  /* blendRead */ nullptr,
228 };
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
void BKE_mesh_copy_parameters_for_eval(struct Mesh *me_dst, const struct Mesh *me_src)
void BKE_mesh_smooth_flag_set(struct Mesh *me, bool use_smooth)
Definition: mesh.cc:1486
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
Definition: mesh.cc:991
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:107
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_Constructive
Definition: BKE_modifier.h:47
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
Volume data-block.
const VolumeGrid * BKE_volume_grid_find_for_read(const struct Volume *volume, const char *name)
bool BKE_volume_load(const struct Volume *volume, const struct Main *bmain)
#define UNUSED_VARS(...)
#define UNUSED(x)
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
struct Main * DEG_get_bmain(const Depsgraph *graph)
#define MAX_NAME
Definition: DNA_defs.h:48
@ eModifierType_VolumeToMesh
@ VOLUME_TO_MESH_USE_SMOOTH_SHADE
VolumeToMeshResolutionMode
@ VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE
@ VOLUME_TO_MESH_RESOLUTION_MODE_GRID
@ VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT
struct VolumeToMeshModifierData VolumeToMeshModifierData
Object is a sort of wrapper for general info.
@ OB_VOLUME
float float4x4[4][4]
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
Definition: MOD_ui_common.c:91
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *input_mesh)
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static Mesh * create_empty_mesh(const Mesh *input_mesh)
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
ModifierTypeInfo modifierType_VolumeToMesh
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
static void panelRegister(ARegionType *region_type)
#define C
Definition: RandGen.cpp:25
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
uint col
std::unique_ptr< T > Ptr
Definition: BLI_any.hh:58
vec_base< float, 3 > float3
Definition: DNA_ID.h:368
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
struct Object * object
Definition: BKE_modifier.h:141
struct DepsNodeHandle * node
Definition: BKE_modifier.h:134
float imat[4][4]
float obmat[4][4]
void * data
struct uiLayout * layout
void * data
Definition: RNA_types.h:38
union blender::bke::VolumeToMeshResolution::@78 settings
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480