Blender  V2.93
MOD_volume_to_mesh.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <vector>
22 
23 #include "BKE_lib_query.h"
24 #include "BKE_mesh.h"
25 #include "BKE_modifier.h"
26 #include "BKE_volume.h"
27 #include "BKE_volume_to_mesh.hh"
28 
29 #include "MOD_modifiertypes.h"
30 #include "MOD_ui_common.h"
31 
32 #include "DNA_mesh_types.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_modifier_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_screen_types.h"
37 #include "DNA_volume_types.h"
38 
39 #include "UI_interface.h"
40 #include "UI_resources.h"
41 
42 #include "RNA_access.h"
43 
44 #include "BLI_float4x4.hh"
45 #include "BLI_math_vector.h"
46 #include "BLI_span.hh"
47 #include "BLI_timeit.hh"
48 
49 #include "DEG_depsgraph_query.h"
50 
51 #ifdef WITH_OPENVDB
52 # include <openvdb/tools/GridTransformer.h>
53 # include <openvdb/tools/VolumeToMesh.h>
54 #endif
55 
56 using blender::float3;
57 using blender::float4x4;
58 using blender::Span;
59 
60 static void initData(ModifierData *md)
61 {
62  VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md);
63  vmmd->object = nullptr;
64  vmmd->threshold = 0.1f;
65  strncpy(vmmd->grid_name, "density", MAX_NAME);
66  vmmd->adaptivity = 0.0f;
68  vmmd->voxel_amount = 32;
69  vmmd->voxel_size = 0.1f;
70  vmmd->flag = 0;
71 }
72 
74 {
75  VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md);
76  DEG_add_modifier_to_transform_relation(ctx->node, "Volume to Mesh Modifier");
77  if (vmmd->object) {
79  ctx->node, vmmd->object, DEG_OB_COMP_GEOMETRY, "Volume to Mesh Modifier");
81  ctx->node, vmmd->object, DEG_OB_COMP_TRANSFORM, "Volume to Mesh Modifier");
82  }
83 }
84 
85 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
86 {
87  VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md);
88  walk(userData, ob, (ID **)&vmmd->object, IDWALK_CB_NOP);
89 }
90 
91 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
92 {
93  uiLayout *layout = panel->layout;
94 
97 
98  uiLayoutSetPropSep(layout, true);
99 
100  {
101  uiLayout *col = uiLayoutColumn(layout, false);
102  uiItemR(col, ptr, "object", 0, nullptr, ICON_NONE);
103  uiItemR(col, ptr, "grid_name", 0, nullptr, ICON_NONE);
104  }
105 
106  {
107  uiLayout *col = uiLayoutColumn(layout, false);
108  uiItemR(col, ptr, "resolution_mode", 0, nullptr, ICON_NONE);
110  uiItemR(col, ptr, "voxel_amount", 0, nullptr, ICON_NONE);
111  }
113  uiItemR(col, ptr, "voxel_size", 0, nullptr, ICON_NONE);
114  }
115  }
116 
117  {
118  uiLayout *col = uiLayoutColumn(layout, false);
119  uiItemR(col, ptr, "threshold", 0, nullptr, ICON_NONE);
120  uiItemR(col, ptr, "adaptivity", 0, nullptr, ICON_NONE);
121  uiItemR(col, ptr, "use_smooth_shade", 0, nullptr, ICON_NONE);
122  }
123 
124  modifier_panel_end(layout, ptr);
125 }
126 
127 static void panelRegister(ARegionType *region_type)
128 {
130 }
131 
132 static Mesh *create_empty_mesh(const Mesh *input_mesh)
133 {
134  Mesh *new_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0);
135  BKE_mesh_copy_settings(new_mesh, input_mesh);
136  return new_mesh;
137 }
138 
139 static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *input_mesh)
140 {
141 #ifdef WITH_OPENVDB
142  VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md);
143  if (vmmd->object == nullptr) {
144  return create_empty_mesh(input_mesh);
145  }
146  if (vmmd->object->type != OB_VOLUME) {
147  return create_empty_mesh(input_mesh);
148  }
150  vmmd->voxel_size == 0.0f) {
151  return create_empty_mesh(input_mesh);
152  }
154  vmmd->voxel_amount == 0) {
155  return create_empty_mesh(input_mesh);
156  }
157 
158  const Volume *volume = static_cast<Volume *>(vmmd->object->data);
159 
160  BKE_volume_load(volume, DEG_get_bmain(ctx->depsgraph));
161  const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, vmmd->grid_name);
162  if (volume_grid == nullptr) {
163  BKE_modifier_set_error(ctx->object, md, "Cannot find '%s' grid", vmmd->grid_name);
164  return create_empty_mesh(input_mesh);
165  }
166 
167  const openvdb::GridBase::ConstPtr local_grid = BKE_volume_grid_openvdb_for_read(volume,
168  volume_grid);
169 
170  openvdb::math::Transform::Ptr transform = local_grid->transform().copy();
171  transform->postMult(openvdb::Mat4d(((float *)vmmd->object->obmat)));
172  openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx->object->imat);
173  /* `imat` had floating point issues and wasn't affine. */
174  imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1));
175  transform->postMult(imat);
176 
177  /* Create a temporary transformed grid. The underlying tree is shared. */
178  openvdb::GridBase::ConstPtr transformed_grid = local_grid->copyGridReplacingTransform(transform);
179 
181  resolution.mode = (VolumeToMeshResolutionMode)vmmd->resolution_mode;
183  resolution.settings.voxel_amount = vmmd->voxel_amount;
184  }
186  resolution.settings.voxel_size = vmmd->voxel_size;
187  }
188 
189  Mesh *mesh = blender::bke::volume_to_mesh(
190  *transformed_grid, resolution, vmmd->threshold, vmmd->adaptivity);
191  if (mesh == nullptr) {
192  BKE_modifier_set_error(ctx->object, md, "Could not generate mesh from grid");
193  return create_empty_mesh(input_mesh);
194  }
195 
196  BKE_mesh_copy_settings(mesh, input_mesh);
199  }
200  return mesh;
201 #else
202  UNUSED_VARS(md);
203  BKE_modifier_set_error(ctx->object, md, "Compiled without OpenVDB");
204  return create_empty_mesh(input_mesh);
205 #endif
206 }
207 
209  /* name */ "Volume to Mesh",
210  /* structName */ "VolumeToMeshModifierData",
211  /* structSize */ sizeof(VolumeToMeshModifierData),
212  /* srna */ &RNA_VolumeToMeshModifier,
214  /* flags */ eModifierTypeFlag_AcceptsMesh,
215  /* icon */ ICON_VOLUME_DATA, /* TODO: Use correct icon. */
216 
217  /* copyData */ BKE_modifier_copydata_generic,
218 
219  /* deformVerts */ nullptr,
220  /* deformMatrices */ nullptr,
221  /* deformVertsEM */ nullptr,
222  /* deformMatricesEM */ nullptr,
223  /* modifyMesh */ modifyMesh,
224  /* modifyHair */ nullptr,
225  /* modifyGeometrySet */ nullptr,
226  /* modifyVolume */ nullptr,
227 
228  /* initData */ initData,
229  /* requiredDataMask */ nullptr,
230  /* freeData */ nullptr,
231  /* isDisabled */ nullptr,
232  /* updateDepsgraph */ updateDepsgraph,
233  /* dependsOnTime */ nullptr,
234  /* dependsOnNormals */ nullptr,
235  /* foreachIDLink */ foreachIDLink,
236  /* foreachTexLink */ nullptr,
237  /* freeRuntimeData */ nullptr,
238  /* panelRegister */ panelRegister,
239  /* blendWrite */ nullptr,
240  /* blendRead */ nullptr,
241 };
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:47
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
Definition: mesh.c:877
void BKE_mesh_smooth_flag_set(struct Mesh *me, const bool use_smooth)
Definition: mesh.c:1392
void BKE_mesh_copy_settings(struct Mesh *me_dst, const struct Mesh *me_src)
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:120
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_Constructive
Definition: BKE_modifier.h:61
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
Volume datablock.
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:62
@ 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
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
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)
StructRNA RNA_VolumeToMeshModifier
#define C
Definition: RandGen.cpp:39
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
Definition: DNA_ID.h:273
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:153
struct Object * object
Definition: BKE_modifier.h:154
struct DepsNodeHandle * node
Definition: BKE_modifier.h:147
float imat[4][4]
float obmat[4][4]
void * data
struct uiLayout * layout
void * data
Definition: RNA_types.h:52
union blender::bke::VolumeToMeshResolution::@77 settings
PointerRNA * ptr
Definition: wm_files.c:3157