Blender V4.3
MOD_remesh.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 by Nicholas Bishop.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
11#include "BLI_math_base.h"
12#include "BLI_threads.h"
13#include "BLI_utildefines.h"
14
15#include "BLT_translation.hh"
16
17#include "DNA_defaults.h"
18#include "DNA_modifier_types.h"
19#include "DNA_screen_types.h"
20
21#include "BKE_mesh.hh"
23#include "BKE_mesh_runtime.hh"
24
25#include "UI_interface.hh"
26#include "UI_resources.hh"
27
28#include "RNA_access.hh"
29#include "RNA_prototypes.hh"
30
31#include "MOD_modifiertypes.hh"
32#include "MOD_ui_common.hh"
33
34#include "GEO_randomize.hh"
35
36#include <cstdlib>
37#include <cstring>
38
39#ifdef WITH_MOD_REMESH
40# include "BLI_math_vector.h"
41
42# include "dualcon.h"
43#endif
44
53
54#ifdef WITH_MOD_REMESH
55
56static void init_dualcon_mesh(DualConInput *input, Mesh *mesh)
57{
58 memset(input, 0, sizeof(DualConInput));
59
60 input->co = (DualConCo)mesh->vert_positions().data();
61 input->co_stride = sizeof(blender::float3);
62 input->totco = mesh->verts_num;
63
64 input->mloop = (DualConLoop)mesh->corner_verts().data();
65 input->loop_stride = sizeof(int);
66
67 input->corner_tris = (DualConTri)mesh->corner_tris().data();
68 input->tri_stride = sizeof(blender::int3);
69 input->tottri = BKE_mesh_runtime_corner_tris_len(mesh);
70
71 const blender::Bounds<blender::float3> bounds = *mesh->bounds_min_max();
72 copy_v3_v3(input->min, bounds.min);
73 copy_v3_v3(input->max, bounds.max);
74}
75
76/* simple structure to hold the output: a CDDM and two counters to
77 * keep track of the current elements */
78struct DualConOutput {
79 Mesh *mesh;
80 blender::float3 *vert_positions;
81 int *face_offsets;
82 int *corner_verts;
83 int curvert, curface;
84};
85
86/* allocate and initialize a DualConOutput */
87static void *dualcon_alloc_output(int totvert, int totquad)
88{
89 DualConOutput *output;
90
91 if (!(output = MEM_cnew<DualConOutput>(__func__))) {
92 return nullptr;
93 }
94
95 output->mesh = BKE_mesh_new_nomain(totvert, 0, totquad, 4 * totquad);
96 output->vert_positions = output->mesh->vert_positions_for_write().data();
97 output->face_offsets = output->mesh->face_offsets_for_write().data();
98 output->corner_verts = output->mesh->corner_verts_for_write().data();
99
100 return output;
101}
102
103static void dualcon_add_vert(void *output_v, const float co[3])
104{
105 DualConOutput *output = static_cast<DualConOutput *>(output_v);
106
107 BLI_assert(output->curvert < output->mesh->verts_num);
108
109 copy_v3_v3(output->vert_positions[output->curvert], co);
110 output->curvert++;
111}
112
113static void dualcon_add_quad(void *output_v, const int vert_indices[4])
114{
115 DualConOutput *output = static_cast<DualConOutput *>(output_v);
116 Mesh *mesh = output->mesh;
117 int i;
118
119 BLI_assert(output->curface < mesh->faces_num);
120 UNUSED_VARS_NDEBUG(mesh);
121
122 output->face_offsets[output->curface] = output->curface * 4;
123 for (i = 0; i < 4; i++) {
124 output->corner_verts[output->curface * 4 + i] = vert_indices[i];
125 }
126
127 output->curface++;
128}
129
130static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext * /*ctx*/, Mesh *mesh)
131{
132 using namespace blender;
134 DualConOutput *output;
135 DualConInput input;
136 Mesh *result;
137 DualConFlags flags = DualConFlags(0);
138 DualConMode mode = DualConMode(0);
139
140 rmd = (RemeshModifierData *)md;
141
142 if (rmd->mode == MOD_REMESH_VOXEL) {
143 /* OpenVDB modes. */
144 if (rmd->voxel_size == 0.0f) {
145 return nullptr;
146 }
147 result = BKE_mesh_remesh_voxel(mesh, rmd->voxel_size, rmd->adaptivity, 0.0f);
148 if (result == nullptr) {
149 return nullptr;
150 }
151 }
152 else {
153 /* Dualcon modes. */
154 init_dualcon_mesh(&input, mesh);
155
156 if (rmd->flag & MOD_REMESH_FLOOD_FILL) {
157 flags = DualConFlags(flags | DUALCON_FLOOD_FILL);
158 }
159
160 switch (rmd->mode) {
162 mode = DUALCON_CENTROID;
163 break;
165 mode = DUALCON_MASS_POINT;
166 break;
169 break;
170 case MOD_REMESH_VOXEL:
171 /* Should have been processed before as an OpenVDB operation. */
172 BLI_assert(false);
173 break;
174 }
175 /* TODO(jbakker): Dualcon crashes when run in parallel. Could be related to incorrect
176 * input data or that the library isn't thread safe.
177 * This was identified when changing the task isolation's during #76553. */
178 static ThreadMutex dualcon_mutex = BLI_MUTEX_INITIALIZER;
179 BLI_mutex_lock(&dualcon_mutex);
180 output = static_cast<DualConOutput *>(dualcon(&input,
181 dualcon_alloc_output,
182 dualcon_add_vert,
183 dualcon_add_quad,
184 flags,
185 mode,
186 rmd->threshold,
187 rmd->hermite_num,
188 rmd->scale,
189 rmd->depth));
190 BLI_mutex_unlock(&dualcon_mutex);
191 result = output->mesh;
192 MEM_freeN(output);
193 }
194
195 bke::mesh_smooth_set(*result, rmd->flag & MOD_REMESH_SMOOTH_SHADING);
196
198 bke::mesh_calc_edges(*result, true, false);
199
201
202 return result;
203}
204
205#else /* !WITH_MOD_REMESH */
206
207static Mesh *modify_mesh(ModifierData * /*md*/, const ModifierEvalContext * /*ctx*/, Mesh *mesh)
208{
209 return mesh;
210}
211
212#endif /* !WITH_MOD_REMESH */
213
214static void panel_draw(const bContext * /*C*/, Panel *panel)
215{
216 uiLayout *layout = panel->layout;
217#ifdef WITH_MOD_REMESH
218 uiLayout *row, *col;
219
220 PointerRNA ob_ptr;
222
223 int mode = RNA_enum_get(ptr, "mode");
224
225 uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
226
227 uiLayoutSetPropSep(layout, true);
228
229 col = uiLayoutColumn(layout, false);
230 if (mode == MOD_REMESH_VOXEL) {
231 uiItemR(col, ptr, "voxel_size", UI_ITEM_NONE, nullptr, ICON_NONE);
232 uiItemR(col, ptr, "adaptivity", UI_ITEM_NONE, nullptr, ICON_NONE);
233 }
234 else {
235 uiItemR(col, ptr, "octree_depth", UI_ITEM_NONE, nullptr, ICON_NONE);
236 uiItemR(col, ptr, "scale", UI_ITEM_NONE, nullptr, ICON_NONE);
237
238 if (mode == MOD_REMESH_SHARP_FEATURES) {
239 uiItemR(col, ptr, "sharpness", UI_ITEM_NONE, nullptr, ICON_NONE);
240 }
241
242 uiItemR(layout, ptr, "use_remove_disconnected", UI_ITEM_NONE, nullptr, ICON_NONE);
243 row = uiLayoutRow(layout, false);
244 uiLayoutSetActive(row, RNA_boolean_get(ptr, "use_remove_disconnected"));
245 uiItemR(layout, ptr, "threshold", UI_ITEM_NONE, nullptr, ICON_NONE);
246 }
247 uiItemR(layout, ptr, "use_smooth_shade", UI_ITEM_NONE, nullptr, ICON_NONE);
248
249 modifier_panel_end(layout, ptr);
250
251#else /* WITH_MOD_REMESH */
252 uiItemL(layout, RPT_("Built without Remesh modifier"), ICON_NONE);
253#endif /* WITH_MOD_REMESH */
254}
255
256static void panel_register(ARegionType *region_type)
257{
259}
260
262 /*idname*/ "Remesh",
263 /*name*/ N_("Remesh"),
264 /*struct_name*/ "RemeshModifierData",
265 /*struct_size*/ sizeof(RemeshModifierData),
266 /*srna*/ &RNA_RemeshModifier,
270 /*icon*/ ICON_MOD_REMESH,
271
272 /*copy_data*/ BKE_modifier_copydata_generic,
273
274 /*deform_verts*/ nullptr,
275 /*deform_matrices*/ nullptr,
276 /*deform_verts_EM*/ nullptr,
277 /*deform_matrices_EM*/ nullptr,
278 /*modify_mesh*/ modify_mesh,
279 /*modify_geometry_set*/ nullptr,
280
281 /*init_data*/ init_data,
282 /*required_data_mask*/ nullptr,
283 /*free_data*/ nullptr,
284 /*is_disabled*/ nullptr,
285 /*update_depsgraph*/ nullptr,
286 /*depends_on_time*/ nullptr,
287 /*depends_on_normals*/ nullptr,
288 /*foreach_ID_link*/ nullptr,
289 /*foreach_tex_link*/ nullptr,
290 /*free_runtime_data*/ nullptr,
291 /*panel_register*/ panel_register,
292 /*blend_write*/ nullptr,
293 /*blend_read*/ nullptr,
294 /*foreach_cache*/ nullptr,
295};
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
Mesh * BKE_mesh_remesh_voxel(const Mesh *mesh, float voxel_size, float adaptivity, float isovalue)
int BKE_mesh_runtime_corner_tris_len(const Mesh *mesh)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define BLI_MUTEX_INITIALIZER
Definition BLI_threads.h:84
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:83
#define UNUSED_VARS_NDEBUG(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define RPT_(msgid)
#define DNA_struct_default_get(struct_name)
@ MOD_REMESH_FLOOD_FILL
@ MOD_REMESH_SMOOTH_SHADING
@ MOD_REMESH_VOXEL
@ MOD_REMESH_MASS_POINT
@ MOD_REMESH_SHARP_FEATURES
@ MOD_REMESH_CENTROID
@ eModifierType_Remesh
struct RemeshModifierData RemeshModifierData
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
Definition MOD_remesh.cc:45
static void panel_register(ARegionType *region_type)
static void panel_draw(const bContext *, Panel *panel)
static Mesh * modify_mesh(ModifierData *, const ModifierEvalContext *, Mesh *mesh)
ModifierTypeInfo modifierType_Remesh
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiItemL(uiLayout *layout, const char *name, int icon)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_EXPAND
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
#define output
DualConMode
Definition dualcon.h:49
@ DUALCON_SHARP_FEATURES
Definition dualcon.h:55
@ DUALCON_CENTROID
Definition dualcon.h:51
@ DUALCON_MASS_POINT
Definition dualcon.h:53
void * dualcon(const DualConInput *input_mesh, DualConAllocOutput alloc_output, DualConAddVert add_vert, DualConAddQuad add_quad, DualConFlags flags, DualConMode mode, float threshold, float hermite_num, float scale, int depth)
unsigned int * DualConLoop
Definition dualcon.h:20
unsigned int(* DualConTri)[3]
Definition dualcon.h:18
float(* DualConCo)[3]
Definition dualcon.h:16
DualConFlags
Definition dualcon.h:45
@ DUALCON_FLOOD_FILL
Definition dualcon.h:46
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void debug_randomize_mesh_order(Mesh *mesh)
Definition randomize.cc:220
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126