Blender  V3.3
MOD_build.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_utildefines.h"
11 
12 #include "BLI_ghash.h"
13 #include "BLI_math_vector.h"
14 #include "BLI_rand.h"
15 
16 #include "BLT_translation.h"
17 
18 #include "DNA_defaults.h"
19 #include "DNA_mesh_types.h"
20 #include "DNA_meshdata_types.h"
21 #include "DNA_object_types.h"
22 #include "DNA_screen_types.h"
23 
24 #include "DEG_depsgraph_query.h"
25 
26 #include "BKE_context.h"
27 #include "BKE_mesh.h"
28 #include "BKE_modifier.h"
29 #include "BKE_particle.h"
30 #include "BKE_scene.h"
31 #include "BKE_screen.h"
32 
33 #include "UI_interface.h"
34 #include "UI_resources.h"
35 
36 #include "RNA_access.h"
37 #include "RNA_prototypes.h"
38 
39 #include "MOD_modifiertypes.h"
40 #include "MOD_ui_common.h"
41 
42 static void initData(ModifierData *md)
43 {
45 
47 
49 }
50 
51 static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
52 {
53  return true;
54 }
55 
56 static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *mesh)
57 {
58  Mesh *result;
60  int i, j, k;
61  int faces_dst_num, edges_dst_num, loops_dst_num = 0;
62  int *vertMap, *edgeMap, *faceMap;
63  float frac;
64  MPoly *mpoly_dst;
65  MLoop *ml_dst, *ml_src /*, *mloop_dst */;
66  GHashIterator gh_iter;
67  /* maps vert indices in old mesh to indices in new mesh */
68  GHash *vertHash = BLI_ghash_int_new("build ve apply gh");
69  /* maps edge indices in new mesh to indices in old mesh */
70  GHash *edgeHash = BLI_ghash_int_new("build ed apply gh");
71  /* maps edge indices in old mesh to indices in new mesh */
72  GHash *edgeHash2 = BLI_ghash_int_new("build ed apply gh");
73 
74  const int vert_src_num = mesh->totvert;
75  const int edge_src_num = mesh->totedge;
76  const int poly_src_num = mesh->totpoly;
77  MPoly *mpoly_src = mesh->mpoly;
78  MLoop *mloop_src = mesh->mloop;
79  MEdge *medge_src = mesh->medge;
80  MVert *mvert_src = mesh->mvert;
81 
82  vertMap = MEM_malloc_arrayN(vert_src_num, sizeof(*vertMap), "build modifier vertMap");
83  edgeMap = MEM_malloc_arrayN(edge_src_num, sizeof(*edgeMap), "build modifier edgeMap");
84  faceMap = MEM_malloc_arrayN(poly_src_num, sizeof(*faceMap), "build modifier faceMap");
85 
86  range_vn_i(vertMap, vert_src_num, 0);
87  range_vn_i(edgeMap, edge_src_num, 0);
88  range_vn_i(faceMap, poly_src_num, 0);
89 
90  struct Scene *scene = DEG_get_input_scene(ctx->depsgraph);
91  frac = (BKE_scene_ctime_get(scene) - bmd->start) / bmd->length;
92  CLAMP(frac, 0.0f, 1.0f);
93  if (bmd->flag & MOD_BUILD_FLAG_REVERSE) {
94  frac = 1.0f - frac;
95  }
96 
97  faces_dst_num = poly_src_num * frac;
98  edges_dst_num = edge_src_num * frac;
99 
100  /* if there's at least one face, build based on faces */
101  if (faces_dst_num) {
102  MPoly *mpoly, *mp;
103  MLoop *ml, *mloop;
104  uintptr_t hash_num, hash_num_alt;
105 
106  if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
107  BLI_array_randomize(faceMap, sizeof(*faceMap), poly_src_num, bmd->seed);
108  }
109 
110  /* get the set of all vert indices that will be in the final mesh,
111  * mapped to the new indices
112  */
113  mpoly = mpoly_src;
114  mloop = mloop_src;
115  hash_num = 0;
116  for (i = 0; i < faces_dst_num; i++) {
117  mp = mpoly + faceMap[i];
118  ml = mloop + mp->loopstart;
119 
120  for (j = 0; j < mp->totloop; j++, ml++) {
121  void **val_p;
122  if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(ml->v), &val_p)) {
123  *val_p = (void *)hash_num;
124  hash_num++;
125  }
126  }
127 
128  loops_dst_num += mp->totloop;
129  }
130  BLI_assert(hash_num == BLI_ghash_len(vertHash));
131 
132  /* get the set of edges that will be in the new mesh (i.e. all edges
133  * that have both verts in the new mesh)
134  */
135  hash_num = 0;
136  hash_num_alt = 0;
137  for (i = 0; i < edge_src_num; i++, hash_num_alt++) {
138  MEdge *me = medge_src + i;
139 
140  if (BLI_ghash_haskey(vertHash, POINTER_FROM_INT(me->v1)) &&
141  BLI_ghash_haskey(vertHash, POINTER_FROM_INT(me->v2))) {
142  BLI_ghash_insert(edgeHash, (void *)hash_num, (void *)hash_num_alt);
143  BLI_ghash_insert(edgeHash2, (void *)hash_num_alt, (void *)hash_num);
144  hash_num++;
145  }
146  }
147  BLI_assert(hash_num == BLI_ghash_len(edgeHash));
148  }
149  else if (edges_dst_num) {
150  MEdge *medge, *me;
151  uintptr_t hash_num;
152 
153  if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
154  BLI_array_randomize(edgeMap, sizeof(*edgeMap), edge_src_num, bmd->seed);
155  }
156 
157  /* get the set of all vert indices that will be in the final mesh,
158  * mapped to the new indices
159  */
160  medge = medge_src;
161  hash_num = 0;
162  BLI_assert(hash_num == BLI_ghash_len(vertHash));
163  for (i = 0; i < edges_dst_num; i++) {
164  void **val_p;
165  me = medge + edgeMap[i];
166 
167  if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(me->v1), &val_p)) {
168  *val_p = (void *)hash_num;
169  hash_num++;
170  }
171  if (!BLI_ghash_ensure_p(vertHash, POINTER_FROM_INT(me->v2), &val_p)) {
172  *val_p = (void *)hash_num;
173  hash_num++;
174  }
175  }
176  BLI_assert(hash_num == BLI_ghash_len(vertHash));
177 
178  /* get the set of edges that will be in the new mesh */
179  for (i = 0; i < edges_dst_num; i++) {
180  j = BLI_ghash_len(edgeHash);
181 
182  BLI_ghash_insert(edgeHash, POINTER_FROM_INT(j), POINTER_FROM_INT(edgeMap[i]));
183  BLI_ghash_insert(edgeHash2, POINTER_FROM_INT(edgeMap[i]), POINTER_FROM_INT(j));
184  }
185  }
186  else {
187  int verts_num = vert_src_num * frac;
188 
189  if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
190  BLI_array_randomize(vertMap, sizeof(*vertMap), vert_src_num, bmd->seed);
191  }
192 
193  /* get the set of all vert indices that will be in the final mesh,
194  * mapped to the new indices
195  */
196  for (i = 0; i < verts_num; i++) {
197  BLI_ghash_insert(vertHash, POINTER_FROM_INT(vertMap[i]), POINTER_FROM_INT(i));
198  }
199  }
200 
201  /* now we know the number of verts, edges and faces, we can create the mesh. */
203  mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), 0, loops_dst_num, faces_dst_num);
204 
205  /* copy the vertices across */
206  GHASH_ITER (gh_iter, vertHash) {
207  MVert source;
208  MVert *dest;
209  int oldIndex = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter));
210  int newIndex = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter));
211 
212  source = mvert_src[oldIndex];
213  dest = &result->mvert[newIndex];
214 
215  CustomData_copy_data(&mesh->vdata, &result->vdata, oldIndex, newIndex, 1);
216  *dest = source;
217  }
218 
219  /* copy the edges across, remapping indices */
220  for (i = 0; i < BLI_ghash_len(edgeHash); i++) {
221  MEdge source;
222  MEdge *dest;
223  int oldIndex = POINTER_AS_INT(BLI_ghash_lookup(edgeHash, POINTER_FROM_INT(i)));
224 
225  source = medge_src[oldIndex];
226  dest = &result->medge[i];
227 
228  source.v1 = POINTER_AS_INT(BLI_ghash_lookup(vertHash, POINTER_FROM_INT(source.v1)));
229  source.v2 = POINTER_AS_INT(BLI_ghash_lookup(vertHash, POINTER_FROM_INT(source.v2)));
230 
231  CustomData_copy_data(&mesh->edata, &result->edata, oldIndex, i, 1);
232  *dest = source;
233  }
234 
235  mpoly_dst = result->mpoly;
236  ml_dst = result->mloop;
237 
238  /* copy the faces across, remapping indices */
239  k = 0;
240  for (i = 0; i < faces_dst_num; i++) {
241  MPoly *source;
242  MPoly *dest;
243 
244  source = mpoly_src + faceMap[i];
245  dest = mpoly_dst + i;
246  CustomData_copy_data(&mesh->pdata, &result->pdata, faceMap[i], i, 1);
247 
248  *dest = *source;
249  dest->loopstart = k;
251  &mesh->ldata, &result->ldata, source->loopstart, dest->loopstart, dest->totloop);
252 
253  ml_src = mloop_src + source->loopstart;
254  for (j = 0; j < source->totloop; j++, k++, ml_src++, ml_dst++) {
255  ml_dst->v = POINTER_AS_INT(BLI_ghash_lookup(vertHash, POINTER_FROM_INT(ml_src->v)));
256  ml_dst->e = POINTER_AS_INT(BLI_ghash_lookup(edgeHash2, POINTER_FROM_INT(ml_src->e)));
257  }
258  }
259 
260  BLI_ghash_free(vertHash, NULL, NULL);
261  BLI_ghash_free(edgeHash, NULL, NULL);
262  BLI_ghash_free(edgeHash2, NULL, NULL);
263 
264  MEM_freeN(vertMap);
265  MEM_freeN(edgeMap);
267 
268  /* TODO(sybren): also copy flags & tags? */
269  return result;
270 }
271 
272 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
273 {
274  uiLayout *layout = panel->layout;
275 
277 
278  uiLayoutSetPropSep(layout, true);
279 
280  uiItemR(layout, ptr, "frame_start", 0, NULL, ICON_NONE);
281  uiItemR(layout, ptr, "frame_duration", 0, NULL, ICON_NONE);
282  uiItemR(layout, ptr, "use_reverse", 0, NULL, ICON_NONE);
283 
284  modifier_panel_end(layout, ptr);
285 }
286 
287 static void random_panel_header_draw(const bContext *UNUSED(C), Panel *panel)
288 {
289  uiLayout *layout = panel->layout;
290 
292 
293  uiItemR(layout, ptr, "use_random_order", 0, NULL, ICON_NONE);
294 }
295 
296 static void random_panel_draw(const bContext *UNUSED(C), Panel *panel)
297 {
298  uiLayout *layout = panel->layout;
299 
301 
302  uiLayoutSetPropSep(layout, true);
303 
304  uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_random_order"));
305  uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE);
306 }
307 
308 static void panelRegister(ARegionType *region_type)
309 {
312  region_type, "randomize", "", random_panel_header_draw, random_panel_draw, panel_type);
313 }
314 
316  /* name */ N_("Build"),
317  /* structName */ "BuildModifierData",
318  /* structSize */ sizeof(BuildModifierData),
319  /* srna */ &RNA_BuildModifier,
322  /* icon */ ICON_MOD_BUILD,
323 
324  /* copyData */ BKE_modifier_copydata_generic,
325 
326  /* deformVerts */ NULL,
327  /* deformMatrices */ NULL,
328  /* deformVertsEM */ NULL,
329  /* deformMatricesEM */ NULL,
330  /* modifyMesh */ modifyMesh,
331  /* modifyGeometrySet */ NULL,
332 
333  /* initData */ initData,
334  /* requiredDataMask */ NULL,
335  /* freeData */ NULL,
336  /* isDisabled */ NULL,
337  /* updateDepsgraph */ NULL,
338  /* dependsOnTime */ dependsOnTime,
339  /* dependsOnNormals */ NULL,
340  /* foreachIDLink */ NULL,
341  /* foreachTexLink */ NULL,
342  /* freeRuntimeData */ NULL,
343  /* panelRegister */ panelRegister,
344  /* blendWrite */ NULL,
345  /* blendRead */ NULL,
346 };
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
struct Mesh * BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
@ eModifierTypeFlag_AcceptsCVs
Definition: BKE_modifier.h:67
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_Nonconstructive
Definition: BKE_modifier.h:49
float BKE_scene_ctime_get(const struct Scene *scene)
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:298
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:822
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:302
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:321
GHash * BLI_ghash_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:734
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:705
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:755
void range_vn_i(int *array_tar, int size, int start)
Definition: math_vector.c:1021
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 POINTER_FROM_INT(i)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
struct Scene * DEG_get_input_scene(const Depsgraph *graph)
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ MOD_BUILD_FLAG_REVERSE
@ MOD_BUILD_FLAG_RANDOMIZE
@ eModifierType_Build
struct BuildModifierData BuildModifierData
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
Definition: MOD_build.c:51
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *mesh)
Definition: MOD_build.c:56
static void random_panel_header_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_build.c:287
static void random_panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_build.c:296
ModifierTypeInfo modifierType_Build
Definition: MOD_build.c:315
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_build.c:272
static void initData(ModifierData *md)
Definition: MOD_build.c:42
static void panelRegister(ARegionType *region_type)
Definition: MOD_build.c:308
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)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define C
Definition: RandGen.cpp:25
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
Scene scene
SyclQueue void * dest
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
ccl_device_inline float frac(float x, int *ix)
const int faceMap[6][4]
Definition: octree.cpp:2817
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
_W64 unsigned int uintptr_t
Definition: stdint.h:119
unsigned int v1
unsigned int v2
unsigned int e
unsigned int v
struct MEdge * medge
CustomData vdata
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
CustomData pdata
int totpoly
CustomData edata
struct MPoly * mpoly
CustomData ldata
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480