Blender  V3.3
MOD_particleinstance.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_listbase.h"
13 #include "BLI_math.h"
14 #include "BLI_rand.h"
15 #include "BLI_string.h"
16 
17 #include "BLT_translation.h"
18 
19 #include "DNA_defaults.h"
20 #include "DNA_mesh_types.h"
21 #include "DNA_meshdata_types.h"
22 #include "DNA_screen_types.h"
23 
24 #include "BKE_context.h"
25 #include "BKE_effect.h"
26 #include "BKE_lattice.h"
27 #include "BKE_lib_query.h"
28 #include "BKE_mesh.h"
29 #include "BKE_modifier.h"
30 #include "BKE_particle.h"
31 #include "BKE_pointcache.h"
32 #include "BKE_screen.h"
33 
34 #include "UI_interface.h"
35 #include "UI_resources.h"
36 
37 #include "RNA_access.h"
38 #include "RNA_prototypes.h"
39 
40 #include "DEG_depsgraph_build.h"
41 #include "DEG_depsgraph_query.h"
42 
43 #include "MOD_modifiertypes.h"
44 #include "MOD_ui_common.h"
45 
46 static void initData(ModifierData *md)
47 {
49 
50  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(pimd, modifier));
51 
53 }
54 
55 static void requiredDataMask(Object *UNUSED(ob),
56  ModifierData *md,
57  CustomData_MeshMasks *r_cddata_masks)
58 {
60 
61  if (pimd->index_layer_name[0] != '\0' || pimd->value_layer_name[0] != '\0') {
62  r_cddata_masks->lmask |= CD_MASK_PROP_BYTE_COLOR;
63  }
64 }
65 
66 static bool isDisabled(const struct Scene *scene, ModifierData *md, bool useRenderParams)
67 {
69  ParticleSystem *psys;
70  ModifierData *ob_md;
71 
72  /* The object type check is only needed here in case we have a placeholder
73  * object assigned (because the library containing the mesh is missing).
74  *
75  * In other cases it should be impossible to have a type mismatch.
76  */
77  if (!pimd->ob || pimd->ob->type != OB_MESH) {
78  return true;
79  }
80 
81  psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
82  if (psys == NULL) {
83  return true;
84  }
85 
86  /* If the psys modifier is disabled we cannot use its data.
87  * First look up the psys modifier from the object, then check if it is enabled.
88  */
89  for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) {
90  if (ob_md->type == eModifierType_ParticleSystem) {
92  if (psmd->psys == psys) {
93  int required_mode;
94 
95  if (useRenderParams) {
96  required_mode = eModifierMode_Render;
97  }
98  else {
99  required_mode = eModifierMode_Realtime;
100  }
101 
102  if (!BKE_modifier_is_enabled(scene, ob_md, required_mode)) {
103  return true;
104  }
105 
106  break;
107  }
108  }
109  }
110 
111  return false;
112 }
113 
115 {
117  if (pimd->ob != NULL) {
119  ctx->node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
121  ctx->node, pimd->ob, DEG_OB_COMP_GEOMETRY, "Particle Instance Modifier");
122  }
123 }
124 
125 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
126 {
128 
129  walk(userData, ob, (ID **)&pimd->ob, IDWALK_CB_NOP);
130 }
131 
133 {
134  const bool between = (psys->part->childtype == PART_CHILD_FACES);
135  ParticleData *pa;
136  int totpart, randp, minp, maxp;
137 
138  if (p >= psys->totpart) {
139  ChildParticle *cpa = psys->child + (p - psys->totpart);
140  pa = psys->particles + (between ? cpa->pa[0] : cpa->parent);
141  }
142  else {
143  pa = psys->particles + p;
144  }
145 
146  if (pa) {
147  if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) {
148  return true;
149  }
150  if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) {
151  return true;
152  }
153  if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) {
154  return true;
155  }
156  if (pa->flag & (PARS_UNEXIST | PARS_NO_DISP)) {
157  return true;
158  }
159  }
160 
161  if (pimd->particle_amount == 1.0f) {
162  /* Early output, all particles are to be instanced. */
163  return false;
164  }
165 
166  /* Randomly skip particles based on desired amount of visible particles. */
167 
168  totpart = psys->totpart + psys->totchild;
169 
170  /* TODO: make randomization optional? */
171  randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart;
172 
173  minp = (int)(totpart * pimd->particle_offset) % (totpart + 1);
174  maxp = (int)(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart + 1);
175 
176  if (maxp > minp) {
177  return randp < minp || randp >= maxp;
178  }
179  if (maxp < minp) {
180  return randp < minp && randp >= maxp;
181  }
182 
183  return true;
184 
185  return false;
186 }
187 
188 static void store_float_in_vcol(MLoopCol *vcol, float float_value)
189 {
190  const uchar value = unit_float_to_uchar_clamp(float_value);
191  vcol->r = vcol->g = vcol->b = value;
192  vcol->a = 1.0f;
193 }
194 
196 {
197  Mesh *result;
201  ParticleSystem *psys = NULL;
202  ParticleData *pa = NULL;
203  MPoly *mpoly, *orig_mpoly;
204  MLoop *mloop, *orig_mloop;
205  MVert *mvert, *orig_mvert;
206  int totvert, totpoly, totloop, totedge;
207  int maxvert, maxpoly, maxloop, maxedge, part_end = 0, part_start;
208  int k, p, p_skip;
209  short track = ctx->object->trackflag % 3, trackneg, axis = pimd->axis;
210  float max_co = 0.0, min_co = 0.0, temp_co[3];
211  float *size = NULL;
212  float spacemat[4][4];
213  const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents;
214  const bool use_children = pimd->flag & eParticleInstanceFlag_Children;
215  bool between;
216 
217  trackneg = ((ctx->object->trackflag > 2) ? 1 : 0);
218 
219  if (pimd->ob == ctx->object) {
220  pimd->ob = NULL;
221  return mesh;
222  }
223 
224  if (pimd->ob) {
225  psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
226  if (psys == NULL || psys->totpart == 0) {
227  return mesh;
228  }
229  }
230  else {
231  return mesh;
232  }
233 
234  part_start = use_parents ? 0 : psys->totpart;
235 
236  part_end = 0;
237  if (use_parents) {
238  part_end += psys->totpart;
239  }
240  if (use_children) {
241  part_end += psys->totchild;
242  }
243 
244  if (part_end == 0) {
245  return mesh;
246  }
247 
248  sim.depsgraph = ctx->depsgraph;
249  sim.scene = scene;
250  sim.ob = pimd->ob;
251  sim.psys = psys;
252  sim.psmd = psys_get_modifier(pimd->ob, psys);
253  between = (psys->part->childtype == PART_CHILD_FACES);
254 
255  if (pimd->flag & eParticleInstanceFlag_UseSize) {
256  float *si;
257  si = size = MEM_calloc_arrayN(part_end, sizeof(float), "particle size array");
258 
259  if (pimd->flag & eParticleInstanceFlag_Parents) {
260  for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++) {
261  *si = pa->size;
262  }
263  }
264 
265  if (pimd->flag & eParticleInstanceFlag_Children) {
266  ChildParticle *cpa = psys->child;
267 
268  for (p = 0; p < psys->totchild; p++, cpa++, si++) {
269  *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
270  }
271  }
272  }
273 
274  switch (pimd->space) {
276  /* particle states are in world space already */
277  unit_m4(spacemat);
278  break;
280  /* get particle states in the particle object's local space */
281  invert_m4_m4(spacemat, pimd->ob->obmat);
282  break;
283  default:
284  /* should not happen */
285  BLI_assert(false);
286  break;
287  }
288 
289  totvert = mesh->totvert;
290  totpoly = mesh->totpoly;
291  totloop = mesh->totloop;
292  totedge = mesh->totedge;
293 
294  /* count particles */
295  maxvert = 0;
296  maxpoly = 0;
297  maxloop = 0;
298  maxedge = 0;
299 
300  for (p = part_start; p < part_end; p++) {
301  if (particle_skip(pimd, psys, p)) {
302  continue;
303  }
304 
305  maxvert += totvert;
306  maxpoly += totpoly;
307  maxloop += totloop;
308  maxedge += totedge;
309  }
310 
311  psys_sim_data_init(&sim);
312 
313  if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
314  float min[3], max[3];
315  INIT_MINMAX(min, max);
317  min_co = min[track];
318  max_co = max[track];
319  }
320 
321  result = BKE_mesh_new_nomain_from_template(mesh, maxvert, maxedge, 0, maxloop, maxpoly);
322 
323  mvert = result->mvert;
324  orig_mvert = mesh->mvert;
325  mpoly = result->mpoly;
326  orig_mpoly = mesh->mpoly;
327  mloop = result->mloop;
328  orig_mloop = mesh->mloop;
329 
330  MLoopCol *mloopcols_index = CustomData_get_layer_named(
331  &result->ldata, CD_PROP_BYTE_COLOR, pimd->index_layer_name);
332  MLoopCol *mloopcols_value = CustomData_get_layer_named(
333  &result->ldata, CD_PROP_BYTE_COLOR, pimd->value_layer_name);
334  int *vert_part_index = NULL;
335  float *vert_part_value = NULL;
336  if (mloopcols_index != NULL) {
337  vert_part_index = MEM_calloc_arrayN(maxvert, sizeof(int), "vertex part index array");
338  }
339  if (mloopcols_value) {
340  vert_part_value = MEM_calloc_arrayN(maxvert, sizeof(float), "vertex part value array");
341  }
342 
343  for (p = part_start, p_skip = 0; p < part_end; p++) {
344  float prev_dir[3];
345  float frame[4]; /* frame orientation quaternion */
346  float p_random = psys_frand(psys, 77091 + 283 * p);
347 
348  /* skip particle? */
349  if (particle_skip(pimd, psys, p)) {
350  continue;
351  }
352 
353  /* set vertices coordinates */
354  for (k = 0; k < totvert; k++) {
356  MVert *inMV;
357  int vindex = p_skip * totvert + k;
358  MVert *mv = mvert + vindex;
359 
360  inMV = orig_mvert + k;
361  CustomData_copy_data(&mesh->vdata, &result->vdata, k, p_skip * totvert + k, 1);
362  *mv = *inMV;
363 
364  if (vert_part_index != NULL) {
365  vert_part_index[vindex] = p;
366  }
367  if (vert_part_value != NULL) {
368  vert_part_value[vindex] = p_random;
369  }
370 
371  /* Change orientation based on object trackflag. */
372  copy_v3_v3(temp_co, mv->co);
373  mv->co[axis] = temp_co[track];
374  mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
375  mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
376 
377  /* get particle state */
378  if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
379  (pimd->flag & eParticleInstanceFlag_Path)) {
380  float ran = 0.0f;
381  if (pimd->random_position != 0.0f) {
382  ran = pimd->random_position * BLI_hash_frand(psys->seed + p);
383  }
384 
386  state.time = pimd->position * (1.0f - ran);
387  }
388  else {
389  state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
390 
391  if (trackneg) {
392  state.time = 1.0f - state.time;
393  }
394 
395  mv->co[axis] = 0.0;
396  }
397 
398  psys_get_particle_on_path(&sim, p, &state, 1);
399 
400  normalize_v3(state.vel);
401 
402  /* Incrementally Rotating Frame (Bishop Frame) */
403  if (k == 0) {
404  float hairmat[4][4];
405  float mat[3][3];
406 
407  if (p < psys->totpart) {
408  pa = psys->particles + p;
409  }
410  else {
411  ChildParticle *cpa = psys->child + (p - psys->totpart);
412  pa = psys->particles + (between ? cpa->pa[0] : cpa->parent);
413  }
414  psys_mat_hair_to_global(sim.ob, sim.psmd->mesh_final, sim.psys->part->from, pa, hairmat);
415  copy_m3_m4(mat, hairmat);
416  /* to quaternion */
417  mat3_to_quat(frame, mat);
418 
419  if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) {
420  float angle = 2.0f * M_PI *
421  (pimd->rotation +
422  pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f));
423  const float eul[3] = {0.0f, 0.0f, angle};
424  float rot[4];
425 
426  eul_to_quat(rot, eul);
427  mul_qt_qtqt(frame, frame, rot);
428  }
429 
430  /* NOTE: direction is same as normal vector currently,
431  * but best to keep this separate so the frame can be
432  * rotated later if necessary
433  */
434  copy_v3_v3(prev_dir, state.vel);
435  }
436  else {
437  float rot[4];
438 
439  /* incrementally rotate along bend direction */
440  rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
441  mul_qt_qtqt(frame, rot, frame);
442 
443  copy_v3_v3(prev_dir, state.vel);
444  }
445 
446  copy_qt_qt(state.rot, frame);
447 #if 0
448  /* Absolute Frame (Frenet Frame) */
449  if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
450  unit_qt(state.rot);
451  }
452  else {
453  float cross[3];
454  float temp[3] = {0.0f, 0.0f, 0.0f};
455  temp[axis] = 1.0f;
456 
457  cross_v3_v3v3(cross, temp, state.vel);
458 
459  /* state.vel[axis] is the only component surviving from a dot product with the axis */
460  axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
461  }
462 #endif
463  }
464  else {
465  state.time = -1.0;
466  psys_get_particle_state(&sim, p, &state, 1);
467  }
468 
469  mul_qt_v3(state.rot, mv->co);
470  if (pimd->flag & eParticleInstanceFlag_UseSize) {
471  mul_v3_fl(mv->co, size[p]);
472  }
473  add_v3_v3(mv->co, state.co);
474 
475  mul_m4_v3(spacemat, mv->co);
476  }
477 
478  /* Create edges and adjust edge vertex indices. */
479  CustomData_copy_data(&mesh->edata, &result->edata, 0, p_skip * totedge, totedge);
480  MEdge *me = &result->medge[p_skip * totedge];
481  for (k = 0; k < totedge; k++, me++) {
482  me->v1 += p_skip * totvert;
483  me->v2 += p_skip * totvert;
484  }
485 
486  /* create polys and loops */
487  for (k = 0; k < totpoly; k++) {
488 
489  MPoly *inMP = orig_mpoly + k;
490  MPoly *mp = mpoly + p_skip * totpoly + k;
491 
492  CustomData_copy_data(&mesh->pdata, &result->pdata, k, p_skip * totpoly + k, 1);
493  *mp = *inMP;
494  mp->loopstart += p_skip * totloop;
495 
496  {
497  MLoop *inML = orig_mloop + inMP->loopstart;
498  MLoop *ml = mloop + mp->loopstart;
499  int j = mp->totloop;
500 
501  CustomData_copy_data(&mesh->ldata, &result->ldata, inMP->loopstart, mp->loopstart, j);
502  for (; j; j--, ml++, inML++) {
503  ml->v = inML->v + (p_skip * totvert);
504  ml->e = inML->e + (p_skip * totedge);
505  const int ml_index = (ml - mloop);
506  if (mloopcols_index != NULL) {
507  const int part_index = vert_part_index[ml->v];
508  store_float_in_vcol(&mloopcols_index[ml_index],
509  (float)part_index / (float)(psys->totpart - 1));
510  }
511  if (mloopcols_value != NULL) {
512  const float part_value = vert_part_value[ml->v];
513  store_float_in_vcol(&mloopcols_value[ml_index], part_value);
514  }
515  }
516  }
517  }
518  p_skip++;
519  }
520 
521  psys_sim_data_free(&sim);
522 
523  if (size) {
524  MEM_freeN(size);
525  }
526 
527  MEM_SAFE_FREE(vert_part_index);
528  MEM_SAFE_FREE(vert_part_value);
529 
530  return result;
531 }
532 
533 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
534 {
535  uiLayout *row;
536  uiLayout *layout = panel->layout;
538 
539  PointerRNA ob_ptr;
541 
542  PointerRNA particle_obj_ptr = RNA_pointer_get(ptr, "object");
543 
544  uiLayoutSetPropSep(layout, true);
545 
546  uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
547  if (!RNA_pointer_is_null(&particle_obj_ptr)) {
548  uiItemPointerR(layout,
549  ptr,
550  "particle_system",
551  &particle_obj_ptr,
552  "particle_systems",
553  IFACE_("Particle System"),
554  ICON_NONE);
555  }
556  else {
557  uiItemR(layout, ptr, "particle_system_index", 0, IFACE_("Particle System"), ICON_NONE);
558  }
559 
560  uiItemS(layout);
561 
562  row = uiLayoutRowWithHeading(layout, true, IFACE_("Create Instances"));
563  uiItemR(row, ptr, "use_normal", toggles_flag, NULL, ICON_NONE);
564  uiItemR(row, ptr, "use_children", toggles_flag, NULL, ICON_NONE);
565  uiItemR(row, ptr, "use_size", toggles_flag, NULL, ICON_NONE);
566 
567  row = uiLayoutRowWithHeading(layout, true, IFACE_("Show"));
568  uiItemR(row, ptr, "show_alive", toggles_flag, NULL, ICON_NONE);
569  uiItemR(row, ptr, "show_dead", toggles_flag, NULL, ICON_NONE);
570  uiItemR(row, ptr, "show_unborn", toggles_flag, NULL, ICON_NONE);
571 
572  uiItemR(layout, ptr, "particle_amount", 0, IFACE_("Amount"), ICON_NONE);
573  uiItemR(layout, ptr, "particle_offset", 0, IFACE_("Offset"), ICON_NONE);
574 
575  uiItemS(layout);
576 
577  uiItemR(layout, ptr, "space", 0, IFACE_("Coordinate Space"), ICON_NONE);
578  row = uiLayoutRow(layout, true);
579  uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
580 
581  modifier_panel_end(layout, ptr);
582 }
583 
584 static void path_panel_draw_header(const bContext *UNUSED(C), Panel *panel)
585 {
586  uiLayout *layout = panel->layout;
587 
589 
590  uiItemR(layout, ptr, "use_path", 0, IFACE_("Create Along Paths"), ICON_NONE);
591 }
592 
593 static void path_panel_draw(const bContext *UNUSED(C), Panel *panel)
594 {
595  uiLayout *col;
596  uiLayout *layout = panel->layout;
597 
598  PointerRNA ob_ptr;
600 
601  uiLayoutSetPropSep(layout, true);
602 
603  uiLayoutSetActive(layout, RNA_boolean_get(ptr, "use_path"));
604 
605  col = uiLayoutColumn(layout, true);
606  uiItemR(col, ptr, "position", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
607  uiItemR(col, ptr, "random_position", UI_ITEM_R_SLIDER, IFACE_("Random"), ICON_NONE);
608  col = uiLayoutColumn(layout, true);
609  uiItemR(col, ptr, "rotation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
610  uiItemR(col, ptr, "random_rotation", UI_ITEM_R_SLIDER, IFACE_("Random"), ICON_NONE);
611 
612  uiItemR(layout, ptr, "use_preserve_shape", 0, NULL, ICON_NONE);
613 }
614 
615 static void layers_panel_draw(const bContext *UNUSED(C), Panel *panel)
616 {
617  uiLayout *col;
618  uiLayout *layout = panel->layout;
619 
620  PointerRNA ob_ptr;
622 
623  PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
624 
625  uiLayoutSetPropSep(layout, true);
626 
627  col = uiLayoutColumn(layout, false);
629  col, ptr, "index_layer_name", &obj_data_ptr, "vertex_colors", IFACE_("Index"), ICON_NONE);
631  col, ptr, "value_layer_name", &obj_data_ptr, "vertex_colors", IFACE_("Value"), ICON_NONE);
632 }
633 
634 static void panelRegister(ARegionType *region_type)
635 {
636  PanelType *panel_type = modifier_panel_register(
639  region_type, "paths", "", path_panel_draw_header, path_panel_draw, panel_type);
640  modifier_subpanel_register(region_type, "layers", "Layers", NULL, layers_panel_draw, panel_type);
641 }
642 
644  /* name */ N_("ParticleInstance"),
645  /* structName */ "ParticleInstanceModifierData",
646  /* structSize */ sizeof(ParticleInstanceModifierData),
647  /* srna */ &RNA_ParticleInstanceModifier,
651  /* icon */ ICON_MOD_PARTICLE_INSTANCE,
652 
653  /* copyData */ BKE_modifier_copydata_generic,
654 
655  /* deformVerts */ NULL,
656  /* deformMatrices */ NULL,
657  /* deformVertsEM */ NULL,
658  /* deformMatricesEM */ NULL,
659  /* modifyMesh */ modifyMesh,
660  /* modifyGeometrySet */ NULL,
661 
662  /* initData */ initData,
663  /* requiredDataMask */ requiredDataMask,
664  /* freeData */ NULL,
665  /* isDisabled */ isDisabled,
666  /* updateDepsgraph */ updateDepsgraph,
667  /* dependsOnTime */ NULL,
668  /* dependsOnNormals */ NULL,
669  /* foreachIDLink */ foreachIDLink,
670  /* foreachTexLink */ NULL,
671  /* freeRuntimeData */ NULL,
672  /* panelRegister */ panelRegister,
673  /* blendWrite */ NULL,
674  /* blendRead */ NULL,
675 };
void * CustomData_get_layer_named(const struct CustomData *data, int type, const char *name)
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
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)
bool BKE_mesh_minmax(const struct Mesh *me, float r_min[3], float r_max[3])
bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode)
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:107
@ eModifierTypeFlag_SupportsMapping
Definition: BKE_modifier.h:68
@ eModifierTypeFlag_EnableInEditmode
Definition: BKE_modifier.h:78
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:69
@ 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 psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, bool vel)
Definition: particle.c:4615
void psys_mat_hair_to_global(struct Object *ob, struct Mesh *mesh, short from, struct ParticleData *pa, float hairmat[4][4])
Definition: particle.c:3935
void psys_sim_data_free(struct ParticleSimulationData *sim)
Definition: particle.c:726
struct ParticleSystemModifierData * psys_get_modifier(struct Object *ob, struct ParticleSystem *psys)
Definition: particle.c:2230
float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time)
void psys_sim_data_init(struct ParticleSimulationData *sim)
Definition: particle.c:685
BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
Definition: BKE_particle.h:248
bool psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, bool always)
Definition: particle.c:4884
#define BLI_assert(a)
Definition: BLI_assert.h:46
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float saacos(float fac)
#define M_PI
Definition: BLI_math_base.h:20
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void unit_m4(float m[4][4])
Definition: rct.c:1090
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void mat3_to_quat(float q[4], const float mat[3][3])
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:59
void unit_qt(float q[4])
Definition: math_rotation.c:27
void eul_to_quat(float quat[4], const float eul[3])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
Definition: math_rotation.c:46
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
MINLINE float normalize_v3(float r[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
Random number functions.
float BLI_hash_frand(unsigned int seed) ATTR_WARN_UNUSED_RESULT
Definition: rand.cc:180
unsigned char uchar
Definition: BLI_sys_types.h:70
#define INIT_MINMAX(min, max)
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
#define CD_MASK_PROP_BYTE_COLOR
@ CD_PROP_BYTE_COLOR
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ eModifierMode_Render
@ eModifierMode_Realtime
@ eParticleInstanceFlag_Parents
@ eParticleInstanceFlag_Alive
@ eParticleInstanceFlag_Dead
@ eParticleInstanceFlag_Children
@ eParticleInstanceFlag_Unborn
@ eParticleInstanceFlag_Path
@ eParticleInstanceFlag_UseSize
@ eParticleInstanceFlag_KeepShape
struct ParticleInstanceModifierData ParticleInstanceModifierData
@ eModifierType_ParticleSystem
@ eModifierType_ParticleInstance
@ eParticleInstanceSpace_World
@ eParticleInstanceSpace_Local
@ OB_MESH
#define PARS_UNEXIST
#define PARS_NO_DISP
#define PSYS_KEYED
#define PART_CHILD_FACES
#define PARS_DEAD
#define PARS_ALIVE
#define PARS_UNBORN
#define PSYS_HAIR_DONE
@ PTCACHE_BAKED
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
ModifierTypeInfo modifierType_ParticleInstance
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static bool isDisabled(const struct Scene *scene, ModifierData *md, bool useRenderParams)
static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static void store_float_in_vcol(MLoopCol *vcol, float float_value)
static void path_panel_draw_header(const bContext *UNUSED(C), Panel *panel)
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
static void path_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void panelRegister(ARegionType *region_type)
static void layers_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
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)
#define C
Definition: RandGen.cpp:25
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
Scene scene
#define rot(x, k)
uint col
const int state
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5167
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:164
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
#define min(a, b)
Definition: sort.c:35
Definition: DNA_ID.h:368
void * first
Definition: DNA_listBase.h:31
unsigned int v1
unsigned int v2
unsigned char a
unsigned char b
unsigned char r
unsigned char g
unsigned int e
unsigned int v
CustomData vdata
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
CustomData pdata
int totpoly
CustomData edata
int totloop
struct MPoly * mpoly
CustomData ldata
struct ModifierData * next
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
struct Object * object
Definition: BKE_modifier.h:141
struct DepsNodeHandle * node
Definition: BKE_modifier.h:134
ListBase particlesystem
ListBase modifiers
float obmat[4][4]
short trackflag
struct uiLayout * layout
struct Depsgraph * depsgraph
Definition: BKE_particle.h:69
struct ParticleSystemModifierData * psmd
Definition: BKE_particle.h:73
struct Scene * scene
Definition: BKE_particle.h:70
struct ParticleSystem * psys
Definition: BKE_particle.h:72
struct Object * ob
Definition: BKE_particle.h:71
struct ParticleSystem * psys
ChildParticle * child
ParticleData * particles
ParticleSettings * part
struct PointCache * pointcache
float max
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480