Blender V5.0
MOD_particleinstance.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
8
9#include "MEM_guardedalloc.h"
10
11#include "BLI_color.hh"
12#include "BLI_listbase.h"
13#include "BLI_math_matrix.h"
14#include "BLI_math_rotation.h"
15#include "BLI_math_vector.h"
16#include "BLI_rand.h"
17#include "BLI_utildefines.h"
18
19#include "BLT_translation.hh"
20
21#include "DNA_defaults.h"
22#include "DNA_mesh_types.h"
23#include "DNA_meshdata_types.h"
24#include "DNA_screen_types.h"
25
26#include "BKE_customdata.hh"
27#include "BKE_lib_query.hh"
28#include "BKE_mesh.hh"
29#include "BKE_modifier.hh"
30#include "BKE_particle.h"
31#include "BKE_pointcache.h"
32
34#include "UI_resources.hh"
35
36#include "RNA_access.hh"
37#include "RNA_prototypes.hh"
38
41
42#include "MOD_ui_common.hh"
43
52
53static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
54{
56
57 if (pimd->index_layer_name[0] != '\0' || pimd->value_layer_name[0] != '\0') {
58 r_cddata_masks->lmask |= CD_MASK_PROP_BYTE_COLOR;
59 }
60}
61
62static bool is_disabled(const Scene *scene, ModifierData *md, bool use_render_params)
63{
65 ParticleSystem *psys;
66
67 /* The object type check is only needed here in case we have a placeholder
68 * object assigned (because the library containing the mesh is missing).
69 *
70 * In other cases it should be impossible to have a type mismatch.
71 */
72 if (!pimd->ob || pimd->ob->type != OB_MESH) {
73 return true;
74 }
75
76 psys = static_cast<ParticleSystem *>(BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1));
77 if (psys == nullptr) {
78 return true;
79 }
80
81 /* If the psys modifier is disabled we cannot use its data.
82 * First look up the psys modifier from the object, then check if it is enabled.
83 */
84 LISTBASE_FOREACH (ModifierData *, ob_md, &pimd->ob->modifiers) {
85 if (ob_md->type == eModifierType_ParticleSystem) {
87 if (psmd->psys == psys) {
88 int required_mode;
89
90 if (use_render_params) {
91 required_mode = eModifierMode_Render;
92 }
93 else {
94 required_mode = eModifierMode_Realtime;
95 }
96
97 if (!BKE_modifier_is_enabled(scene, ob_md, required_mode)) {
98 return true;
99 }
100
101 break;
102 }
103 }
104 }
105
106 return false;
107}
108
110{
112 if (pimd->ob != nullptr) {
114 ctx->node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
116 ctx->node, pimd->ob, DEG_OB_COMP_GEOMETRY, "Particle Instance Modifier");
117 }
118}
119
120static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
121{
123
124 walk(user_data, ob, (ID **)&pimd->ob, IDWALK_CB_NOP);
125}
126
128{
129 const bool between = (psys->part->childtype == PART_CHILD_FACES);
130 ParticleData *pa;
131 int totpart, randp, minp, maxp;
132
133 if (p >= psys->totpart) {
134 ChildParticle *cpa = psys->child + (p - psys->totpart);
135 pa = psys->particles + (between ? cpa->pa[0] : cpa->parent);
136 }
137 else {
138 pa = psys->particles + p;
139 }
140
141 if (pa) {
142 if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) {
143 return true;
144 }
145 if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) {
146 return true;
147 }
148 if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) {
149 return true;
150 }
151 if (pa->flag & (PARS_UNEXIST | PARS_NO_DISP)) {
152 return true;
153 }
154 }
155
156 if (pimd->particle_amount == 1.0f) {
157 /* Early output, all particles are to be instanced. */
158 return false;
159 }
160
161 /* Randomly skip particles based on desired amount of visible particles. */
162
163 totpart = psys->totpart + psys->totchild;
164
165 /* TODO: make randomization optional? */
166 randp = int(psys_frand(psys, 3578 + p) * totpart) % totpart;
167
168 minp = int(totpart * pimd->particle_offset) % (totpart + 1);
169 maxp = int(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart + 1);
170
171 if (maxp > minp) {
172 return randp < minp || randp >= maxp;
173 }
174 if (maxp < minp) {
175 return randp < minp && randp >= maxp;
176 }
177
178 return true;
179}
180
181static void store_float_in_vcol(blender::ColorGeometry4b *vcol, float float_value)
182{
183 const uchar value = unit_float_to_uchar_clamp(float_value);
184 vcol->r = vcol->g = vcol->b = value;
185 vcol->a = 1.0f;
186}
187
188static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
189{
190 using namespace blender;
191 Mesh *result;
195 ParticleSystem *psys = nullptr;
196 ParticleData *pa = nullptr;
197 int totvert, faces_num, totloop, totedge;
198 int maxvert, maxpoly, maxloop, maxedge, part_end = 0, part_start;
199 int k, p, p_skip;
200 const uint track = uint(ctx->object->trackflag) % 3;
201 short trackneg, axis = pimd->axis;
202 float max_co = 0.0, min_co = 0.0, temp_co[3];
203 float *size = nullptr;
204 float spacemat[4][4];
205 const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents;
206 const bool use_children = pimd->flag & eParticleInstanceFlag_Children;
207 bool between;
208
209 trackneg = ((ctx->object->trackflag > 2) ? 1 : 0);
210
211 if (pimd->ob == ctx->object) {
212 pimd->ob = nullptr;
213 return mesh;
214 }
215
216 if (pimd->ob) {
217 psys = static_cast<ParticleSystem *>(BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1));
218 if (psys == nullptr || psys->totpart == 0) {
219 return mesh;
220 }
221 }
222 else {
223 return mesh;
224 }
225
226 part_start = use_parents ? 0 : psys->totpart;
227
228 part_end = 0;
229 if (use_parents) {
230 part_end += psys->totpart;
231 }
232 if (use_children) {
233 part_end += psys->totchild;
234 }
235
236 if (part_end == 0) {
237 return mesh;
238 }
239
240 sim.depsgraph = ctx->depsgraph;
241 sim.scene = scene;
242 sim.ob = pimd->ob;
243 sim.psys = psys;
244 sim.psmd = psys_get_modifier(pimd->ob, psys);
245 between = (psys->part->childtype == PART_CHILD_FACES);
246
248 float *si;
249 si = size = MEM_calloc_arrayN<float>(part_end, __func__);
250
252 for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++) {
253 *si = pa->size;
254 }
255 }
256
258 ChildParticle *cpa = psys->child;
259
260 for (p = 0; p < psys->totchild; p++, cpa++, si++) {
261 *si = psys_get_child_size(psys, cpa, 0.0f, nullptr);
262 }
263 }
264 }
265
266 switch (pimd->space) {
268 /* particle states are in world space already */
269 unit_m4(spacemat);
270 break;
272 /* get particle states in the particle object's local space */
273 invert_m4_m4(spacemat, pimd->ob->object_to_world().ptr());
274 break;
275 default:
276 /* should not happen */
277 BLI_assert(false);
278 break;
279 }
280
281 totvert = mesh->verts_num;
282 faces_num = mesh->faces_num;
283 totloop = mesh->corners_num;
284 totedge = mesh->edges_num;
285
286 /* count particles */
287 maxvert = 0;
288 maxpoly = 0;
289 maxloop = 0;
290 maxedge = 0;
291
292 for (p = part_start; p < part_end; p++) {
293 if (particle_skip(pimd, psys, p)) {
294 continue;
295 }
296
297 maxvert += totvert;
298 maxpoly += faces_num;
299 maxloop += totloop;
300 maxedge += totedge;
301 }
302
303 psys_sim_data_init(&sim);
304
305 if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
306 if (const std::optional<blender::Bounds<blender::float3>> bounds = mesh->bounds_min_max()) {
307 min_co = bounds->min[track];
308 max_co = bounds->max[track];
309 }
310 }
311
312 result = BKE_mesh_new_nomain_from_template(mesh, maxvert, maxedge, maxpoly, maxloop);
313
314 const blender::OffsetIndices orig_faces = mesh->faces();
315 const blender::Span<int> orig_corner_verts = mesh->corner_verts();
316 const blender::Span<int> orig_corner_edges = mesh->corner_edges();
317 blender::MutableSpan<blender::float3> positions = result->vert_positions_for_write();
318 blender::MutableSpan<blender::int2> edges = result->edges_for_write();
319 blender::MutableSpan<int> face_offsets = result->face_offsets_for_write();
320 blender::MutableSpan<int> corner_verts = result->corner_verts_for_write();
321 blender::MutableSpan<int> corner_edges = result->corner_edges_for_write();
322 blender::bke::MutableAttributeAccessor attributes = result->attributes_for_write();
323 bke::SpanAttributeWriter mloopcols_index =
326 bke::SpanAttributeWriter mloopcols_value =
329 int *vert_part_index = nullptr;
330 float *vert_part_value = nullptr;
331 if (mloopcols_index) {
332 vert_part_index = MEM_calloc_arrayN<int>(maxvert, "vertex part index array");
333 }
334 if (mloopcols_value) {
335 vert_part_value = MEM_calloc_arrayN<float>(maxvert, "vertex part value array");
336 }
337
338 for (p = part_start, p_skip = 0; p < part_end; p++) {
339 float prev_dir[3];
340 float frame[4]; /* frame orientation quaternion */
341 float p_random = psys_frand(psys, 77091 + 283 * p);
342
343 /* skip particle? */
344 if (particle_skip(pimd, psys, p)) {
345 continue;
346 }
347
348 /* set vertices coordinates */
349 for (k = 0; k < totvert; k++) {
351 int vindex = p_skip * totvert + k;
352
353 CustomData_copy_data(&mesh->vert_data, &result->vert_data, k, vindex, 1);
354
355 if (vert_part_index != nullptr) {
356 vert_part_index[vindex] = p;
357 }
358 if (vert_part_value != nullptr) {
359 vert_part_value[vindex] = p_random;
360 }
361
362 /* Change orientation based on object trackflag. */
363 copy_v3_v3(temp_co, positions[vindex]);
364 positions[vindex][axis] = temp_co[track];
365 positions[vindex][(axis + 1) % 3] = temp_co[(track + 1) % 3];
366 positions[vindex][(axis + 2) % 3] = temp_co[(track + 2) % 3];
367
368 /* get particle state */
369 if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
371 {
372 float ran = 0.0f;
373 if (pimd->random_position != 0.0f) {
374 ran = pimd->random_position * BLI_hash_frand(psys->seed + p);
375 }
376
378 state.time = pimd->position * (1.0f - ran);
379 }
380 else {
381 state.time = (positions[vindex][axis] - min_co) / (max_co - min_co) * pimd->position *
382 (1.0f - ran);
383
384 if (trackneg) {
385 state.time = 1.0f - state.time;
386 }
387
388 positions[vindex][axis] = 0.0;
389 }
390
391 psys_get_particle_on_path(&sim, p, &state, true);
392
393 normalize_v3(state.vel);
394
395 /* Incrementally Rotating Frame (Bishop Frame) */
396 if (k == 0) {
397 float hairmat[4][4];
398 float mat[3][3];
399
400 if (p < psys->totpart) {
401 pa = psys->particles + p;
402 }
403 else {
404 ChildParticle *cpa = psys->child + (p - psys->totpart);
405 pa = psys->particles + (between ? cpa->pa[0] : cpa->parent);
406 }
407 psys_mat_hair_to_global(sim.ob, sim.psmd->mesh_final, sim.psys->part->from, pa, hairmat);
408 copy_m3_m4(mat, hairmat);
409 /* to quaternion */
410 mat3_to_quat(frame, mat);
411
412 if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) {
413 float angle = 2.0f * M_PI *
414 (pimd->rotation +
415 pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f));
416 const float eul[3] = {0.0f, 0.0f, angle};
417 float rot[4];
418
419 eul_to_quat(rot, eul);
420 mul_qt_qtqt(frame, frame, rot);
421 }
422
423 /* NOTE: direction is same as normal vector currently,
424 * but best to keep this separate so the frame can be
425 * rotated later if necessary
426 */
427 copy_v3_v3(prev_dir, state.vel);
428 }
429 else {
430 float rot[4];
431
432 /* incrementally rotate along bend direction */
434 mul_qt_qtqt(frame, rot, frame);
435
436 copy_v3_v3(prev_dir, state.vel);
437 }
438
439 copy_qt_qt(state.rot, frame);
440#if 0
441 /* Absolute Frame (Frenet Frame) */
442 if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
443 unit_qt(state.rot);
444 }
445 else {
446 float cross[3];
447 float temp[3] = {0.0f, 0.0f, 0.0f};
448 temp[axis] = 1.0f;
449
450 cross_v3_v3v3(cross, temp, state.vel);
451
452 /* state.vel[axis] is the only component surviving from a dot product with the axis */
454 }
455#endif
456 }
457 else {
458 state.time = -1.0;
459 psys_get_particle_state(&sim, p, &state, true);
460 }
461
462 mul_qt_v3(state.rot, positions[vindex]);
464 mul_v3_fl(positions[vindex], size[p]);
465 }
466 add_v3_v3(positions[vindex], state.co);
467
468 mul_m4_v3(spacemat, positions[vindex]);
469 }
470
471 /* Create edges and adjust edge vertex indices. */
472 CustomData_copy_data(&mesh->edge_data, &result->edge_data, 0, p_skip * totedge, totedge);
473 blender::int2 *edge = &edges[p_skip * totedge];
474 for (k = 0; k < totedge; k++, edge++) {
475 (*edge)[0] += p_skip * totvert;
476 (*edge)[1] += p_skip * totvert;
477 }
478
479 /* create faces and loops */
480 for (k = 0; k < faces_num; k++) {
481 const blender::IndexRange in_face = orig_faces[k];
482
483 CustomData_copy_data(&mesh->face_data, &result->face_data, k, p_skip * faces_num + k, 1);
484 const int dst_face_start = in_face.start() + p_skip * totloop;
485 face_offsets[p_skip * faces_num + k] = dst_face_start;
486
487 {
488 int orig_corner_i = in_face.start();
489 int dst_corner_i = dst_face_start;
490 int j = in_face.size();
491
493 &mesh->corner_data, &result->corner_data, in_face.start(), dst_face_start, j);
494 for (; j; j--, orig_corner_i++, dst_corner_i++) {
495 corner_verts[dst_corner_i] = orig_corner_verts[orig_corner_i] + (p_skip * totvert);
496 corner_edges[dst_corner_i] = orig_corner_edges[orig_corner_i] + (p_skip * totedge);
497 const int vert = corner_verts[dst_corner_i];
498 if (mloopcols_index) {
499 const int part_index = vert_part_index[vert];
500 store_float_in_vcol(&mloopcols_index.span[dst_corner_i],
501 float(part_index) / float(psys->totpart - 1));
502 }
503 if (mloopcols_value) {
504 const float part_value = vert_part_value[vert];
505 store_float_in_vcol(&mloopcols_value.span[dst_corner_i], part_value);
506 }
507 }
508 }
509 }
510 p_skip++;
511 }
512
513 psys_sim_data_free(&sim);
514
515 if (size) {
517 }
518
519 MEM_SAFE_FREE(vert_part_index);
520 MEM_SAFE_FREE(vert_part_value);
521
522 mloopcols_index.finish();
523 mloopcols_value.finish();
524
525 return result;
526}
527
528static void panel_draw(const bContext * /*C*/, Panel *panel)
529{
530 uiLayout *row;
531 uiLayout *layout = panel->layout;
533
534 PointerRNA ob_ptr;
536
537 PointerRNA particle_obj_ptr = RNA_pointer_get(ptr, "object");
538
539 layout->use_property_split_set(true);
540
541 layout->prop(ptr, "object", UI_ITEM_NONE, std::nullopt, ICON_NONE);
542 if (!RNA_pointer_is_null(&particle_obj_ptr)) {
543 layout->prop_search(ptr,
544 "particle_system",
545 &particle_obj_ptr,
546 "particle_systems",
547 IFACE_("Particle System"),
548 ICON_NONE);
549 }
550 else {
551 layout->prop(ptr, "particle_system_index", UI_ITEM_NONE, IFACE_("Particle System"), ICON_NONE);
552 }
553
554 layout->separator();
555
556 row = &layout->row(true, IFACE_("Create Instances"));
557 row->prop(ptr, "use_normal", toggles_flag, std::nullopt, ICON_NONE);
558 row->prop(ptr, "use_children", toggles_flag, std::nullopt, ICON_NONE);
559 row->prop(ptr, "use_size", toggles_flag, std::nullopt, ICON_NONE);
560
561 row = &layout->row(true, IFACE_("Show"));
562 row->prop(ptr, "show_alive", toggles_flag, std::nullopt, ICON_NONE);
563 row->prop(ptr, "show_dead", toggles_flag, std::nullopt, ICON_NONE);
564 row->prop(ptr, "show_unborn", toggles_flag, std::nullopt, ICON_NONE);
565
566 layout->prop(ptr,
567 "particle_amount",
570 ICON_NONE);
571 layout->prop(ptr, "particle_offset", UI_ITEM_NONE, IFACE_("Offset"), ICON_NONE);
572
573 layout->separator();
574
575 layout->prop(ptr, "space", UI_ITEM_NONE, IFACE_("Coordinate Space"), ICON_NONE);
576 row = &layout->row(true);
577 row->prop(ptr, "axis", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
578
580}
581
582static void path_panel_draw_header(const bContext * /*C*/, Panel *panel)
583{
584 uiLayout *layout = panel->layout;
585
587
588 layout->prop(ptr, "use_path", UI_ITEM_NONE, IFACE_("Create Along Paths"), ICON_NONE);
589}
590
591static void path_panel_draw(const bContext * /*C*/, Panel *panel)
592{
593 uiLayout *col;
594 uiLayout *layout = panel->layout;
595
596 PointerRNA ob_ptr;
598
599 layout->use_property_split_set(true);
600
601 layout->active_set(RNA_boolean_get(ptr, "use_path"));
602
603 col = &layout->column(true);
604 col->prop(ptr, "position", UI_ITEM_R_SLIDER, std::nullopt, ICON_NONE);
605 col->prop(ptr, "random_position", UI_ITEM_R_SLIDER, IFACE_("Random"), ICON_NONE);
606 col = &layout->column(true);
607 col->prop(ptr, "rotation", UI_ITEM_R_SLIDER, std::nullopt, ICON_NONE);
608 col->prop(ptr, "random_rotation", UI_ITEM_R_SLIDER, IFACE_("Random"), ICON_NONE);
609
610 layout->prop(ptr, "use_preserve_shape", UI_ITEM_NONE, std::nullopt, ICON_NONE);
611}
612
613static void layers_panel_draw(const bContext * /*C*/, Panel *panel)
614{
615 uiLayout *col;
616 uiLayout *layout = panel->layout;
617
618 PointerRNA ob_ptr;
620
621 PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
622
623 layout->use_property_split_set(true);
624
625 col = &layout->column(false);
626 col->prop_search(
627 ptr, "index_layer_name", &obj_data_ptr, "vertex_colors", IFACE_("Index"), ICON_NONE);
628 col->prop_search(
629 ptr, "value_layer_name", &obj_data_ptr, "vertex_colors", IFACE_("Value"), ICON_NONE);
630}
631
632static void panel_register(ARegionType *region_type)
633{
637 region_type, "paths", "", path_panel_draw_header, path_panel_draw, panel_type);
639 region_type, "layers", "Layers", nullptr, layers_panel_draw, panel_type);
640}
641
643 /*idname*/ "ParticleInstance",
644 /*name*/ N_("ParticleInstance"),
645 /*struct_name*/ "ParticleInstanceModifierData",
646 /*struct_size*/ sizeof(ParticleInstanceModifierData),
647 /*srna*/ &RNA_ParticleInstanceModifier,
651 /*icon*/ ICON_MOD_PARTICLE_INSTANCE,
652
653 /*copy_data*/ BKE_modifier_copydata_generic,
654
655 /*deform_verts*/ nullptr,
656 /*deform_matrices*/ nullptr,
657 /*deform_verts_EM*/ nullptr,
658 /*deform_matrices_EM*/ nullptr,
659 /*modify_mesh*/ modify_mesh,
660 /*modify_geometry_set*/ nullptr,
661
662 /*init_data*/ init_data,
663 /*required_data_mask*/ required_data_mask,
664 /*free_data*/ nullptr,
665 /*is_disabled*/ is_disabled,
666 /*update_depsgraph*/ update_depsgraph,
667 /*depends_on_time*/ nullptr,
668 /*depends_on_normals*/ nullptr,
669 /*foreach_ID_link*/ foreach_ID_link,
670 /*foreach_tex_link*/ nullptr,
671 /*free_runtime_data*/ nullptr,
672 /*panel_register*/ panel_register,
673 /*blend_write*/ nullptr,
674 /*blend_read*/ nullptr,
675 /*foreach_cache*/ nullptr,
676 /*foreach_working_space_color*/ nullptr,
677};
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)
@ IDWALK_CB_NOP
Mesh * BKE_mesh_new_nomain_from_template(const Mesh *me_src, int verts_num, int edges_num, int faces_num, int corners_num)
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, bool vel)
Definition particle.cc:4592
struct ParticleSystemModifierData * psys_get_modifier(struct Object *ob, struct ParticleSystem *psys)
Definition particle.cc:2155
void psys_mat_hair_to_global(struct Object *ob, struct Mesh *mesh, short from, struct ParticleData *pa, float hairmat[4][4])
Definition particle.cc:3900
void psys_sim_data_free(struct ParticleSimulationData *sim)
Definition particle.cc:633
float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time)
Definition particle.cc:4503
void psys_sim_data_init(struct ParticleSimulationData *sim)
Definition particle.cc:592
BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
bool psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, bool always)
Definition particle.cc:4879
#define BLI_assert(a)
Definition BLI_assert.h:46
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
MINLINE float safe_acosf(float a)
#define M_PI
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void unit_m4(float m[4][4])
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])
void unit_qt(float q[4])
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])
void copy_qt_qt(float q[4], const float a[4])
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])
MINLINE float normalize_v3(float n[3])
Random number functions.
float BLI_hash_frand(unsigned int seed) ATTR_WARN_UNUSED_RESULT
Definition rand.cc:148
unsigned char uchar
unsigned int uint
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_COUNTABLE
void DEG_add_object_relation(DepsNodeHandle *node_handle, Object *object, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
#define CD_MASK_PROP_BYTE_COLOR
#define DNA_struct_default_get(struct_name)
@ eModifierMode_Render
@ eModifierMode_Realtime
@ eParticleInstanceFlag_Parents
@ eParticleInstanceFlag_Alive
@ eParticleInstanceFlag_Dead
@ eParticleInstanceFlag_Children
@ eParticleInstanceFlag_Unborn
@ eParticleInstanceFlag_Path
@ eParticleInstanceFlag_UseSize
@ eParticleInstanceFlag_KeepShape
@ eModifierType_ParticleSystem
@ eModifierType_ParticleInstance
@ eParticleInstanceSpace_World
@ eParticleInstanceSpace_Local
@ OB_MESH
@ PSYS_HAIR_DONE
@ PSYS_KEYED
@ PARS_ALIVE
@ PARS_DEAD
@ PARS_UNBORN
@ PARS_NO_DISP
@ PARS_UNEXIST
@ PART_CHILD_FACES
@ PTCACHE_BAKED
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
static bool is_disabled
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void required_data_mask(ModifierData *, CustomData_MeshMasks *r_cddata_masks)
static void panel_draw(const bContext *, Panel *panel)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_array.cc:862
static void init_data(ModifierData *md)
ModifierTypeInfo modifierType_ParticleInstance
static void panel_register(ARegionType *region_type)
static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
static void store_float_in_vcol(blender::ColorGeometry4b *vcol, float float_value)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void path_panel_draw_header(const bContext *, Panel *panel)
static void layers_panel_draw(const bContext *, Panel *panel)
static void panel_draw(const bContext *, Panel *panel)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static void path_panel_draw(const bContext *, Panel *panel)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
#define UI_ITEM_NONE
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
ChannelStorageType r
ChannelStorageType g
ChannelStorageType b
ChannelStorageType a
constexpr int64_t size() const
constexpr int64_t start() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
#define rot(x, k)
uint col
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
static void update_depsgraph(tGraphSliderOp *gso)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
static ulong state[N]
VecBase< int32_t, 2 > int2
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
bool RNA_pointer_is_null(const PointerRNA *ptr)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition DNA_ID.h:414
int corners_num
CustomData edge_data
int edges_num
CustomData corner_data
CustomData face_data
CustomData vert_data
int faces_num
int verts_num
ListBase particlesystem
ListBase modifiers
short trackflag
struct uiLayout * layout
struct Depsgraph * depsgraph
struct ParticleSystemModifierData * psmd
struct Scene * scene
struct ParticleSystem * psys
struct Object * ob
struct ParticleSystem * psys
ChildParticle * child
ParticleData * particles
ParticleSettings * part
struct PointCache * pointcache
uiLayout & column(bool align)
void prop_search(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop, PropertyRNA *item_searchpropname, std::optional< blender::StringRefNull > name, int icon, bool results_are_suggestions)
void active_set(bool active)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiLayout & row(bool align)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238