Blender V4.3
MOD_build.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
11#include "BLI_utildefines.h"
12
13#include "BLI_ghash.h"
14#include "BLI_math_vector.h"
15#include "BLI_rand.h"
16
17#include "BLT_translation.hh"
18
19#include "DNA_defaults.h"
20#include "DNA_mesh_types.h"
21#include "DNA_object_types.h"
22#include "DNA_screen_types.h"
23
25
26#include "BKE_customdata.hh"
27#include "BKE_mesh.hh"
28#include "BKE_modifier.hh"
29#include "BKE_scene.hh"
30
31#include "UI_interface.hh"
32#include "UI_resources.hh"
33
34#include "RNA_access.hh"
35#include "RNA_prototypes.hh"
36
37#include "MOD_ui_common.hh"
38
47
48static bool depends_on_time(Scene * /*scene*/, ModifierData * /*md*/)
49{
50 return true;
51}
52
53static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
54{
55 Mesh *result;
57 int i, j, k;
58 int faces_dst_num, edges_dst_num, loops_dst_num = 0;
59 float frac;
60 GHashIterator gh_iter;
61 /* maps vert indices in old mesh to indices in new mesh */
62 GHash *vertHash = BLI_ghash_int_new("build ve apply gh");
63 /* maps edge indices in new mesh to indices in old mesh */
64 GHash *edgeHash = BLI_ghash_int_new("build ed apply gh");
65 /* maps edge indices in old mesh to indices in new mesh */
66 GHash *edgeHash2 = BLI_ghash_int_new("build ed apply gh");
67
68 const int vert_src_num = mesh->verts_num;
69 const blender::Span<blender::int2> edges_src = mesh->edges();
70 const blender::OffsetIndices faces_src = mesh->faces();
71 const blender::Span<int> corner_verts_src = mesh->corner_verts();
72 const blender::Span<int> corner_edges_src = mesh->corner_edges();
73
74 int *vertMap = static_cast<int *>(MEM_malloc_arrayN(vert_src_num, sizeof(int), __func__));
75 int *edgeMap = static_cast<int *>(MEM_malloc_arrayN(edges_src.size(), sizeof(int), __func__));
76 int *faceMap = static_cast<int *>(MEM_malloc_arrayN(faces_src.size(), sizeof(int), __func__));
77
78 range_vn_i(vertMap, vert_src_num, 0);
79 range_vn_i(edgeMap, edges_src.size(), 0);
80 range_vn_i(faceMap, faces_src.size(), 0);
81
82 Scene *scene = DEG_get_input_scene(ctx->depsgraph);
83 frac = (BKE_scene_ctime_get(scene) - bmd->start) / bmd->length;
84 CLAMP(frac, 0.0f, 1.0f);
85 if (bmd->flag & MOD_BUILD_FLAG_REVERSE) {
86 frac = 1.0f - frac;
87 }
88
89 faces_dst_num = faces_src.size() * frac;
90 edges_dst_num = edges_src.size() * frac;
91
92 /* if there's at least one face, build based on faces */
93 if (faces_dst_num) {
94 uintptr_t hash_num, hash_num_alt;
95
96 if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
97 BLI_array_randomize(faceMap, sizeof(*faceMap), faces_src.size(), bmd->seed);
98 }
99
100 /* get the set of all vert indices that will be in the final mesh,
101 * mapped to the new indices
102 */
103 hash_num = 0;
104 for (i = 0; i < faces_dst_num; i++) {
105 const blender::IndexRange face = faces_src[faceMap[i]];
106 for (j = 0; j < face.size(); j++) {
107 const int vert_i = corner_verts_src[face[j]];
108 void **val_p;
109 if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(vert_i), &val_p)) {
110 *val_p = (void *)hash_num;
111 hash_num++;
112 }
113 }
114
115 loops_dst_num += face.size();
116 }
117 BLI_assert(hash_num == BLI_ghash_len(vertHash));
118
119 /* get the set of edges that will be in the new mesh (i.e. all edges
120 * that have both verts in the new mesh)
121 */
122 hash_num = 0;
123 hash_num_alt = 0;
124 for (i = 0; i < edges_src.size(); i++, hash_num_alt++) {
125 const blender::int2 &edge = edges_src[i];
126
127 if (BLI_ghash_haskey(vertHash, POINTER_FROM_INT(edge[0])) &&
128 BLI_ghash_haskey(vertHash, POINTER_FROM_INT(edge[1])))
129 {
130 BLI_ghash_insert(edgeHash, (void *)hash_num, (void *)hash_num_alt);
131 BLI_ghash_insert(edgeHash2, (void *)hash_num_alt, (void *)hash_num);
132 hash_num++;
133 }
134 }
135 BLI_assert(hash_num == BLI_ghash_len(edgeHash));
136 }
137 else if (edges_dst_num) {
138 uintptr_t hash_num;
139
140 if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
141 BLI_array_randomize(edgeMap, sizeof(*edgeMap), edges_src.size(), bmd->seed);
142 }
143
144 /* get the set of all vert indices that will be in the final mesh,
145 * mapped to the new indices
146 */
147 const blender::int2 *edges = edges_src.data();
148 hash_num = 0;
149 BLI_assert(hash_num == BLI_ghash_len(vertHash));
150 for (i = 0; i < edges_dst_num; i++) {
151 void **val_p;
152 const blender::int2 &edge = edges[edgeMap[i]];
153
154 if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(edge[0]), &val_p)) {
155 *val_p = (void *)hash_num;
156 hash_num++;
157 }
158 if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(edge[1]), &val_p)) {
159 *val_p = (void *)hash_num;
160 hash_num++;
161 }
162 }
163 BLI_assert(hash_num == BLI_ghash_len(vertHash));
164
165 /* get the set of edges that will be in the new mesh */
166 for (i = 0; i < edges_dst_num; i++) {
167 j = BLI_ghash_len(edgeHash);
168
169 BLI_ghash_insert(edgeHash, POINTER_FROM_INT(j), POINTER_FROM_INT(edgeMap[i]));
170 BLI_ghash_insert(edgeHash2, POINTER_FROM_INT(edgeMap[i]), POINTER_FROM_INT(j));
171 }
172 }
173 else {
174 int verts_num = vert_src_num * frac;
175
176 if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
177 BLI_array_randomize(vertMap, sizeof(*vertMap), vert_src_num, bmd->seed);
178 }
179
180 /* get the set of all vert indices that will be in the final mesh,
181 * mapped to the new indices
182 */
183 for (i = 0; i < verts_num; i++) {
184 BLI_ghash_insert(vertHash, POINTER_FROM_INT(vertMap[i]), POINTER_FROM_INT(i));
185 }
186 }
187
188 /* now we know the number of verts, edges and faces, we can create the mesh. */
190 mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), faces_dst_num, loops_dst_num);
191 blender::MutableSpan<blender::int2> result_edges = result->edges_for_write();
192 blender::MutableSpan<int> result_face_offsets = result->face_offsets_for_write();
193 blender::MutableSpan<int> result_corner_verts = result->corner_verts_for_write();
194 blender::MutableSpan<int> result_corner_edges = result->corner_edges_for_write();
195
196 /* copy the vertices across */
197 GHASH_ITER (gh_iter, vertHash) {
198 int oldIndex = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter));
199 int newIndex = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter));
200 CustomData_copy_data(&mesh->vert_data, &result->vert_data, oldIndex, newIndex, 1);
201 }
202
203 /* copy the edges across, remapping indices */
204 for (i = 0; i < BLI_ghash_len(edgeHash); i++) {
205 blender::int2 source;
206 blender::int2 *dest;
207 int oldIndex = POINTER_AS_INT(BLI_ghash_lookup(edgeHash, POINTER_FROM_INT(i)));
208
209 source = edges_src[oldIndex];
210 dest = &result_edges[i];
211
212 source[0] = POINTER_AS_INT(BLI_ghash_lookup(vertHash, POINTER_FROM_INT(source[0])));
213 source[1] = POINTER_AS_INT(BLI_ghash_lookup(vertHash, POINTER_FROM_INT(source[1])));
214
215 CustomData_copy_data(&mesh->edge_data, &result->edge_data, oldIndex, i, 1);
216 *dest = source;
217 }
218
219 /* copy the faces across, remapping indices */
220 k = 0;
221 for (i = 0; i < faces_dst_num; i++) {
222 const blender::IndexRange src_face = faces_src[faceMap[i]];
223 result_face_offsets[i] = k;
224
225 CustomData_copy_data(&mesh->face_data, &result->face_data, faceMap[i], i, 1);
226
228 &mesh->corner_data, &result->corner_data, src_face.start(), k, src_face.size());
229
230 for (j = 0; j < src_face.size(); j++, k++) {
231 const int vert_src = corner_verts_src[src_face[j]];
232 const int edge_src = corner_edges_src[src_face[j]];
233 result_corner_verts[k] = POINTER_AS_INT(
234 BLI_ghash_lookup(vertHash, POINTER_FROM_INT(vert_src)));
235 result_corner_edges[k] = POINTER_AS_INT(
236 BLI_ghash_lookup(edgeHash2, POINTER_FROM_INT(edge_src)));
237 }
238 }
239
240 BLI_ghash_free(vertHash, nullptr, nullptr);
241 BLI_ghash_free(edgeHash, nullptr, nullptr);
242 BLI_ghash_free(edgeHash2, nullptr, nullptr);
243
244 MEM_freeN(vertMap);
245 MEM_freeN(edgeMap);
247
248 /* TODO(sybren): also copy flags & tags? */
249 return result;
250}
251
252static void panel_draw(const bContext * /*C*/, Panel *panel)
253{
254 uiLayout *layout = panel->layout;
255
257
258 uiLayoutSetPropSep(layout, true);
259
260 uiItemR(layout, ptr, "frame_start", UI_ITEM_NONE, nullptr, ICON_NONE);
261 uiItemR(layout, ptr, "frame_duration", UI_ITEM_NONE, nullptr, ICON_NONE);
262 uiItemR(layout, ptr, "use_reverse", UI_ITEM_NONE, nullptr, ICON_NONE);
263
264 modifier_panel_end(layout, ptr);
265}
266
267static void random_panel_header_draw(const bContext * /*C*/, Panel *panel)
268{
269 uiLayout *layout = panel->layout;
270
272
273 uiItemR(layout, ptr, "use_random_order", UI_ITEM_NONE, nullptr, ICON_NONE);
274}
275
276static void random_panel_draw(const bContext * /*C*/, Panel *panel)
277{
278 uiLayout *layout = panel->layout;
279
281
282 uiLayoutSetPropSep(layout, true);
283
284 uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_random_order"));
285 uiItemR(layout, ptr, "seed", UI_ITEM_NONE, nullptr, ICON_NONE);
286}
287
288static void panel_register(ARegionType *region_type)
289{
292 region_type, "randomize", "", random_panel_header_draw, random_panel_draw, panel_type);
293}
294
296 /*idname*/ "Build",
297 /*name*/ N_("Build"),
298 /*struct_name*/ "BuildModifierData",
299 /*struct_size*/ sizeof(BuildModifierData),
300 /*srna*/ &RNA_BuildModifier,
303 /*icon*/ ICON_MOD_BUILD,
304
305 /*copy_data*/ BKE_modifier_copydata_generic,
306
307 /*deform_verts*/ nullptr,
308 /*deform_matrices*/ nullptr,
309 /*deform_verts_EM*/ nullptr,
310 /*deform_matrices_EM*/ nullptr,
311 /*modify_mesh*/ modify_mesh,
312 /*modify_geometry_set*/ nullptr,
313
314 /*init_data*/ init_data,
315 /*required_data_mask*/ nullptr,
316 /*free_data*/ nullptr,
317 /*is_disabled*/ nullptr,
318 /*update_depsgraph*/ nullptr,
319 /*depends_on_time*/ depends_on_time,
320 /*depends_on_normals*/ nullptr,
321 /*foreach_ID_link*/ nullptr,
322 /*foreach_tex_link*/ nullptr,
323 /*free_runtime_data*/ nullptr,
324 /*panel_register*/ panel_register,
325 /*blend_write*/ nullptr,
326 /*blend_read*/ nullptr,
327 /*foreach_cache*/ nullptr,
328};
CustomData interface, see also DNA_customdata_types.h.
void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
Mesh * BKE_mesh_new_nomain_from_template(const Mesh *me_src, int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_AcceptsMesh
float BKE_scene_ctime_get(const Scene *scene)
Definition scene.cc:2317
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:299
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:819
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:303
#define GHASH_ITER(gh_iter_, ghash_)
Definition BLI_ghash.h:322
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:702
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.c:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
GHash * BLI_ghash_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:752
void range_vn_i(int *array_tar, int size, int start)
Random number functions.
void BLI_array_randomize(void *data, unsigned int elem_size, unsigned int elem_num, unsigned int seed)
Definition rand.cc:188
#define CLAMP(a, b, c)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
Scene * DEG_get_input_scene(const Depsgraph *graph)
#define DNA_struct_default_get(struct_name)
@ eModifierType_Build
struct BuildModifierData BuildModifierData
@ MOD_BUILD_FLAG_REVERSE
@ MOD_BUILD_FLAG_RANDOMIZE
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
Definition MOD_build.cc:39
static void panel_register(ARegionType *region_type)
Definition MOD_build.cc:288
static void random_panel_draw(const bContext *, Panel *panel)
Definition MOD_build.cc:276
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_build.cc:53
ModifierTypeInfo modifierType_Build
Definition MOD_build.cc:295
static void random_panel_header_draw(const bContext *, Panel *panel)
Definition MOD_build.cc:267
static void panel_draw(const bContext *, Panel *panel)
Definition MOD_build.cc:252
static bool depends_on_time(Scene *, ModifierData *)
Definition MOD_build.cc:48
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
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 uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
constexpr int64_t size() const
constexpr int64_t start() const
constexpr const T * data() const
Definition BLI_span.hh:216
constexpr int64_t size() const
Definition BLI_span.hh:253
CCL_NAMESPACE_BEGIN ccl_device_inline float frac(float x, ccl_private int *ix)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
const int faceMap[6][4]
Definition octree.cpp:2829
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
_W64 unsigned int uintptr_t
Definition stdint.h:119
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126