Blender V4.3
particle.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 by Janne Karhu. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9/* Allow using deprecated functionality for .blend file I/O. */
10#define DNA_DEPRECATED_ALLOW
11
12#include <algorithm>
13#include <cmath>
14#include <cstdlib>
15#include <cstring>
16#include <optional>
17
18#include "MEM_guardedalloc.h"
19
20#include "DNA_defaults.h"
21
22#include "DNA_cloth_types.h"
24#include "DNA_curve_types.h"
26#include "DNA_fluid_types.h"
27#include "DNA_key_types.h"
28#include "DNA_material_types.h"
29#include "DNA_mesh_types.h"
30#include "DNA_meshdata_types.h"
32#include "DNA_particle_types.h"
33#include "DNA_scene_types.h"
34
35#include "BLI_blenlib.h"
36#include "BLI_kdopbvh.h"
37#include "BLI_kdtree.h"
38#include "BLI_linklist.h"
39#include "BLI_math_base_safe.h"
40#include "BLI_math_geom.h"
41#include "BLI_math_matrix.h"
42#include "BLI_math_rotation.h"
43#include "BLI_math_vector.h"
44#include "BLI_rand.h"
45#include "BLI_task.h"
46#include "BLI_threads.h"
47#include "BLI_utildefines.h"
48
49#include "BLT_translation.hh"
50
51#include "BKE_anim_path.h"
52#include "BKE_boids.h"
53#include "BKE_cloth.hh"
54#include "BKE_collection.hh"
55#include "BKE_colortools.hh"
56#include "BKE_customdata.hh"
57#include "BKE_deform.hh"
58#include "BKE_displist.h"
59#include "BKE_effect.h"
60#include "BKE_idtype.hh"
61#include "BKE_key.hh"
62#include "BKE_lattice.hh"
63#include "BKE_layer.hh"
64#include "BKE_lib_id.hh"
65#include "BKE_lib_query.hh"
66#include "BKE_material.h"
67#include "BKE_mesh.hh"
69#include "BKE_modifier.hh"
70#include "BKE_object.hh"
71#include "BKE_particle.h"
72#include "BKE_pointcache.h"
73#include "BKE_scene.hh"
74#include "BKE_texture.h"
75
76#include "DEG_depsgraph.hh"
79
80#include "RE_texture.h"
81
82#include "BLO_read_write.hh"
83
84#include "particle_private.h"
85
86using blender::float3;
87
88static void fluid_free_settings(SPHFluidSettings *fluid);
89
90static void particle_settings_init(ID *id)
91{
92 ParticleSettings *particle_settings = (ParticleSettings *)id;
93 BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(particle_settings, id));
94
96
97 particle_settings->effector_weights = BKE_effector_add_weights(nullptr);
98 particle_settings->pd = BKE_partdeflect_new(PFIELD_NULL);
99 particle_settings->pd2 = BKE_partdeflect_new(PFIELD_NULL);
100}
101
102static void particle_settings_copy_data(Main * /*bmain*/,
103 std::optional<Library *> /*owner_library*/,
104 ID *id_dst,
105 const ID *id_src,
106 const int /*flag*/)
107{
108 ParticleSettings *particle_settings_dst = (ParticleSettings *)id_dst;
109 const ParticleSettings *partticle_settings_src = (const ParticleSettings *)id_src;
110
111 particle_settings_dst->pd = BKE_partdeflect_copy(partticle_settings_src->pd);
112 particle_settings_dst->pd2 = BKE_partdeflect_copy(partticle_settings_src->pd2);
113 particle_settings_dst->effector_weights = static_cast<EffectorWeights *>(
114 MEM_dupallocN(partticle_settings_src->effector_weights));
115 particle_settings_dst->fluid = static_cast<SPHFluidSettings *>(
116 MEM_dupallocN(partticle_settings_src->fluid));
117
118 if (partticle_settings_src->clumpcurve) {
119 particle_settings_dst->clumpcurve = BKE_curvemapping_copy(partticle_settings_src->clumpcurve);
120 }
121 if (partticle_settings_src->roughcurve) {
122 particle_settings_dst->roughcurve = BKE_curvemapping_copy(partticle_settings_src->roughcurve);
123 }
124 if (partticle_settings_src->twistcurve) {
125 particle_settings_dst->twistcurve = BKE_curvemapping_copy(partticle_settings_src->twistcurve);
126 }
127
128 particle_settings_dst->boids = boid_copy_settings(partticle_settings_src->boids);
129
130 for (int a = 0; a < MAX_MTEX; a++) {
131 if (partticle_settings_src->mtex[a]) {
132 particle_settings_dst->mtex[a] = static_cast<MTex *>(
133 MEM_dupallocN(partticle_settings_src->mtex[a]));
134 }
135 }
136
137 BLI_duplicatelist(&particle_settings_dst->instance_weights,
138 &partticle_settings_src->instance_weights);
139}
140
142{
143 ParticleSettings *particle_settings = (ParticleSettings *)id;
144
145 for (int a = 0; a < MAX_MTEX; a++) {
146 MEM_SAFE_FREE(particle_settings->mtex[a]);
147 }
148
149 if (particle_settings->clumpcurve) {
150 BKE_curvemapping_free(particle_settings->clumpcurve);
151 }
152 if (particle_settings->roughcurve) {
153 BKE_curvemapping_free(particle_settings->roughcurve);
154 }
155 if (particle_settings->twistcurve) {
156 BKE_curvemapping_free(particle_settings->twistcurve);
157 }
158
159 BKE_partdeflect_free(particle_settings->pd);
160 BKE_partdeflect_free(particle_settings->pd2);
161
162 MEM_SAFE_FREE(particle_settings->effector_weights);
163
164 BLI_freelistN(&particle_settings->instance_weights);
165
166 boid_free_settings(particle_settings->boids);
167 fluid_free_settings(particle_settings->fluid);
168}
169
171{
172 ParticleSettings *psett = reinterpret_cast<ParticleSettings *>(id);
174
179
180 for (int i = 0; i < MAX_MTEX; i++) {
181 if (psett->mtex[i]) {
183 BKE_texture_mtex_foreach_id(data, psett->mtex[i]));
184 }
185 }
186
187 if (psett->effector_weights) {
189 }
190
191 if (psett->pd) {
194 }
195 if (psett->pd2) {
198 }
199
200 if (psett->boids) {
202 LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
203 if (ELEM(rule->type, eBoidRuleType_Avoid, eBoidRuleType_Goal)) {
204 BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
206 }
207 else if (rule->type == eBoidRuleType_FollowLeader) {
210 }
211 }
212 }
213 }
214
217 }
218
220 BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, psett->force_group, IDWALK_CB_NOP);
221 }
222}
223
225{
227
228 LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
229 switch (rule->type) {
232 BLO_write_struct(writer, BoidRuleGoalAvoid, rule);
233 break;
236 break;
239 break;
242 break;
244 BLO_write_struct(writer, BoidRuleFight, rule);
245 break;
246 default:
247 BLO_write_struct(writer, BoidRule, rule);
248 break;
249 }
250 }
251#if 0
252 BoidCondition *cond = state->conditions.first;
253 for (; cond; cond = cond->next) {
254 BLO_write_struct(writer, BoidCondition, cond);
255 }
256#endif
257}
258
259static void particle_settings_blend_write(BlendWriter *writer, ID *id, const void *id_address)
260{
262
263 /* write LibData */
264 BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id);
265 BKE_id_blend_write(writer, &part->id);
266
267 BLO_write_struct(writer, PartDeflect, part->pd);
268 BLO_write_struct(writer, PartDeflect, part->pd2);
269 BLO_write_struct(writer, EffectorWeights, part->effector_weights);
270
271 if (part->clumpcurve) {
272 BKE_curvemapping_blend_write(writer, part->clumpcurve);
273 }
274 if (part->roughcurve) {
275 BKE_curvemapping_blend_write(writer, part->roughcurve);
276 }
277 if (part->twistcurve) {
278 BKE_curvemapping_blend_write(writer, part->twistcurve);
279 }
280
281 LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
282 /* update indices, but only if dw->ob is set (can be nullptr after loading e.g.) */
283 if (dw->ob != nullptr) {
284 dw->index = 0;
285 if (part->instance_collection) { /* can be nullptr if lining fails or set to None */
286 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) {
287 if (object == dw->ob) {
288 break;
289 }
290 dw->index++;
291 }
293 }
294 }
296 }
297
298 if (part->boids && part->phystype == PART_PHYS_BOIDS) {
299 BLO_write_struct(writer, BoidSettings, part->boids);
300
301 LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
302 write_boid_state(writer, state);
303 }
304 }
305 if (part->fluid && part->phystype == PART_PHYS_FLUID) {
306 BLO_write_struct(writer, SPHFluidSettings, part->fluid);
307 }
308
309 for (int a = 0; a < MAX_MTEX; a++) {
310 if (part->mtex[a]) {
311 BLO_write_struct(writer, MTex, part->mtex[a]);
312 }
313 }
314}
315
319
321{
323
324 BLO_read_struct(reader, PartDeflect, &part->pd);
325 BLO_read_struct(reader, PartDeflect, &part->pd2);
328
329 BLO_read_struct(reader, CurveMapping, &part->clumpcurve);
330 if (part->clumpcurve) {
331 BKE_curvemapping_blend_read(reader, part->clumpcurve);
332 }
333 BLO_read_struct(reader, CurveMapping, &part->roughcurve);
334 if (part->roughcurve) {
335 BKE_curvemapping_blend_read(reader, part->roughcurve);
336 }
337 BLO_read_struct(reader, CurveMapping, &part->twistcurve);
338 if (part->twistcurve) {
339 BKE_curvemapping_blend_read(reader, part->twistcurve);
340 }
341
342 BLO_read_struct(reader, EffectorWeights, &part->effector_weights);
343 if (!part->effector_weights) {
344 part->effector_weights = BKE_effector_add_weights(part->force_group);
345 }
346
347 BLO_read_struct_list(reader, ParticleDupliWeight, &part->instance_weights);
348
349 BLO_read_struct(reader, BoidSettings, &part->boids);
350 BLO_read_struct(reader, SPHFluidSettings, &part->fluid);
351
352 if (part->boids) {
353 BLO_read_struct_list(reader, BoidState, &part->boids->states);
354
355 LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
356 BLO_read_struct_list(reader, BoidRule, &state->rules);
357#if 0
358 /* Not implemented yet. */
359 BLO_read_struct_list(reader, BoidCondition, &state->conditions);
360 BLO_read_struct_list(reader, BoidAction, &state->actions);
361#endif
362 }
363 }
364 for (int a = 0; a < MAX_MTEX; a++) {
365 BLO_read_struct(reader, MTex, &part->mtex[a]);
366 }
367
368 /* Protect against integer overflow vulnerability. */
369 CLAMP(part->trail_count, 1, 100000);
370}
371
373{
374 ParticleSettings *part = reinterpret_cast<ParticleSettings *>(id);
375
376 if (part->instance_weights.first && !part->instance_collection) {
377 BLI_freelistN(&part->instance_weights);
378 }
379}
380
382 /*id_code*/ ID_PA,
383 /*id_filter*/ FILTER_ID_PA,
384 /*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_GR | FILTER_ID_TE,
385 /*main_listbase_index*/ INDEX_ID_PA,
386 /*struct_size*/ sizeof(ParticleSettings),
387 /*name*/ "ParticleSettings",
388 /*name_plural*/ N_("particles"),
389 /*translation_context*/ BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
390 /*flags*/ 0,
391 /*asset_type_info*/ nullptr,
392
393 /*init_data*/ particle_settings_init,
394 /*copy_data*/ particle_settings_copy_data,
395 /*free_data*/ particle_settings_free_data,
396 /*make_local*/ nullptr,
397 /*foreach_id*/ particle_settings_foreach_id,
398 /*foreach_cache*/ nullptr,
399 /*foreach_path*/ nullptr,
400 /*owner_pointer_get*/ nullptr,
401
402 /*blend_write*/ particle_settings_blend_write,
403 /*blend_read_data*/ particle_settings_blend_read_data,
404 /*blend_read_after_liblink*/ particle_settings_blend_read_after_liblink,
405
406 /*blend_read_undo_preserve*/ nullptr,
407
408 /*lib_override_apply_post*/ nullptr,
409};
410
414
416{
417 RNG *rng = BLI_rng_new_srandom(5831); /* arbitrary */
418 for (int i = 0; i < PSYS_FRAND_COUNT; i++) {
422 }
423 BLI_rng_free(rng);
424}
425
428 ChildParticle *cpa,
429 short cpa_from,
430 int cpa_num,
431 float *cpa_fuv,
432 float *orco,
433 ParticleTexture *ptex);
434static void get_cpa_texture(Mesh *mesh,
435 ParticleSystem *psys,
436 ParticleSettings *part,
437 ParticleData *par,
438 int child_index,
439 int face_index,
440 const float fw[4],
441 float *orco,
442 ParticleTexture *ptex,
443 int event,
444 float cfra);
445
447{
448 ParticleSettings *part = psys->part;
450 int tot = 0;
451
453 {
454 if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {
455 }
456 else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {
457 }
458 else {
459 tot++;
460 }
461 }
462 return tot;
463}
464int count_particles_mod(ParticleSystem *psys, int totgr, int cur)
465{
466 ParticleSettings *part = psys->part;
468 int tot = 0;
469
471 {
472 if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {
473 }
474 else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {
475 }
476 else if (p % totgr == cur) {
477 tot++;
478 }
479 }
480 return tot;
481}
482/* We allocate path cache memory in chunks instead of a big contiguous
483 * chunk, windows' memory allocator fails to find big blocks of memory often. */
484
485#define PATH_CACHE_BUF_SIZE 1024
486
488{
489 return (key->segments > 0) ? (key + (key->segments - 1)) : key;
490}
491
492static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int totkeys)
493{
494 LinkData *buf;
495 ParticleCacheKey **cache;
496 int i, totkey, totbufkey;
497
498 tot = std::max(tot, 1);
499 totkey = 0;
500 cache = static_cast<ParticleCacheKey **>(MEM_callocN(tot * sizeof(void *), "PathCacheArray"));
501
502 while (totkey < tot) {
503 totbufkey = std::min(tot - totkey, PATH_CACHE_BUF_SIZE);
504 buf = static_cast<LinkData *>(MEM_callocN(sizeof(LinkData), "PathCacheLinkData"));
505 buf->data = MEM_callocN(sizeof(ParticleCacheKey) * totbufkey * totkeys, "ParticleCacheKey");
506
507 for (i = 0; i < totbufkey; i++) {
508 cache[totkey + i] = ((ParticleCacheKey *)buf->data) + i * totkeys;
509 }
510
511 totkey += totbufkey;
512 BLI_addtail(bufs, buf);
513 }
514
515 return cache;
516}
517
519{
520 if (cache) {
521 MEM_freeN(cache);
522 }
523
524 LISTBASE_FOREACH (LinkData *, buf, bufs) {
525 MEM_freeN(buf->data);
526 }
527 BLI_freelistN(bufs);
528}
529
530/************************************************/
531/* Getting stuff */
532/************************************************/
533
535{
536 if (ob == nullptr) {
537 return nullptr;
538 }
539
541 if (psys->flag & PSYS_CURRENT) {
542 return psys;
543 }
544 }
545
546 return nullptr;
547}
549{
550 ParticleSystem *psys;
551 short i;
552
553 if (ob == nullptr) {
554 return 0;
555 }
556
557 for (psys = static_cast<ParticleSystem *>(ob->particlesystem.first), i = 0; psys;
558 psys = psys->next, i++)
559 {
560 if (psys->flag & PSYS_CURRENT) {
561 return i;
562 }
563 }
564
565 return i;
566}
567void psys_set_current_num(Object *ob, int index)
568{
569 ParticleSystem *psys;
570 short i;
571
572 if (ob == nullptr) {
573 return;
574 }
575
576 for (psys = static_cast<ParticleSystem *>(ob->particlesystem.first), i = 0; psys;
577 psys = psys->next, i++)
578 {
579 if (i == index) {
580 psys->flag |= PSYS_CURRENT;
581 }
582 else {
583 psys->flag &= ~PSYS_CURRENT;
584 }
585 }
586}
587
589{
590 ParticleSystem *psys = sim->psys;
591 ParticleSettings *part = psys->part;
592
593 /* Prepare lattice deform. */
594 psys->lattice_deform_data = nullptr;
595 if (psys_in_edit_mode(sim->depsgraph, sim->psys) == 0) {
596 Object *lattice = nullptr;
598 bool for_render = DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER;
599 int mode = for_render ? eModifierMode_Render : eModifierMode_Realtime;
600
601 for (; md; md = md->next) {
602 if (md->type == eModifierType_Lattice) {
603 if (md->mode & mode) {
605 lattice = lmd->object;
606 psys->lattice_strength = lmd->strength;
607 }
608
609 break;
610 }
611 }
612 if (lattice) {
614 }
615 }
616
617 /* Prepare curvemapping tables. */
618 if ((part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && part->clumpcurve) {
619 BKE_curvemapping_init(part->clumpcurve);
620 }
621 if ((part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && part->roughcurve) {
622 BKE_curvemapping_init(part->roughcurve);
623 }
624 if ((part->child_flag & PART_CHILD_USE_TWIST_CURVE) && part->twistcurve) {
625 BKE_curvemapping_init(part->twistcurve);
626 }
627}
628
630{
631 ParticleSystem *psys = sim->psys;
632
633 if (psys->lattice_deform_data) {
635 psys->lattice_deform_data = nullptr;
636 }
637}
638
640{
641 ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
642
643 for (; psys; psys = psys->next) {
644 psys->flag |= PSYS_DISABLED;
645 }
646}
648{
649 ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
650
651 for (; psys; psys = psys->next) {
652 psys->flag &= ~PSYS_DISABLED;
653 }
654}
655
657{
658 if (psys->orig_psys == nullptr) {
659 return psys;
660 }
661 return psys->orig_psys;
662}
663
665{
666 Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
667 if (object_eval == object) {
668 return psys;
669 }
670 ParticleSystem *psys_eval = static_cast<ParticleSystem *>(object_eval->particlesystem.first);
671 while (psys_eval != nullptr) {
672 if (psys_eval->orig_psys == psys) {
673 return psys_eval;
674 }
675 psys_eval = psys_eval->next;
676 }
677 return psys_eval;
678}
679
681{
682 if (psys->orig_psys == nullptr) {
683 return psys->edit;
684 }
685 return psys->orig_psys->edit;
686}
687
688bool psys_in_edit_mode(Depsgraph *depsgraph, const ParticleSystem *psys)
689{
690 const Scene *scene = DEG_get_input_scene(depsgraph);
692 BKE_view_layer_synced_ensure(scene, view_layer);
693 const Object *object = BKE_view_layer_active_object_get(view_layer);
694 if (object == nullptr) {
695 /* TODO(sergey): Needs double-check with multi-object edit. */
696 return false;
697 }
698 const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
699 if (object->mode != OB_MODE_PARTICLE_EDIT) {
700 return false;
701 }
702 const ParticleSystem *psys_orig = psys_orig_get((ParticleSystem *)psys);
703 return (psys_orig->edit || psys->pointcache->edit) && (use_render_params == false);
704}
705
706bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params)
707{
709
710 if (psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part) {
711 return false;
712 }
713
714 psmd = psys_get_modifier(ob, psys);
715
716 if (!psmd) {
717 return false;
718 }
719
720 if (use_render_params) {
721 if (!(psmd->modifier.mode & eModifierMode_Render)) {
722 return false;
723 }
724 }
725 else if (!(psmd->modifier.mode & eModifierMode_Realtime)) {
726 return false;
727 }
728
729 return true;
730}
731
733{
734 if (psys->part && psys->part->type == PART_HAIR) {
735 return (psys->flag & PSYS_EDITED || (psys->edit && psys->edit->edited));
736 }
737
738 return (psys->pointcache->edit && psys->pointcache->edit->edited);
739}
740
742{
743 /* Find object pointers based on index. If the collection is linked from
744 * another library linking may not have the object pointers available on
745 * file load, so we have to retrieve them later. See #49273. */
746 ListBase instance_collection_objects = {nullptr, nullptr};
747
748 if (part->instance_collection) {
749 instance_collection_objects = BKE_collection_object_cache_get(part->instance_collection);
750 }
751
752 LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
753 if (dw->ob == nullptr) {
754 Base *base = static_cast<Base *>(BLI_findlink(&instance_collection_objects, dw->index));
755 if (base != nullptr) {
756 dw->ob = base->object;
757 }
758 }
759 }
760}
761
763{
764 ParticleDupliWeight *dw, *tdw;
765
766 if (part->ren_as != PART_DRAW_GR || !part->instance_collection) {
767 BLI_freelistN(&part->instance_weights);
768 return;
769 }
770
771 /* Find object pointers. */
773
774 /* Remove nullptr objects, that were removed from the collection. */
775 dw = static_cast<ParticleDupliWeight *>(part->instance_weights.first);
776 while (dw) {
777 if (dw->ob == nullptr ||
778 !BKE_collection_has_object_recursive(part->instance_collection, dw->ob))
779 {
780 tdw = dw->next;
781 BLI_freelinkN(&part->instance_weights, dw);
782 dw = tdw;
783 }
784 else {
785 dw = dw->next;
786 }
787 }
788
789 /* Add new objects in the collection. */
790 int index = 0;
791 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) {
792 dw = static_cast<ParticleDupliWeight *>(part->instance_weights.first);
793 while (dw && dw->ob != object) {
794 dw = dw->next;
795 }
796
797 if (!dw) {
798 dw = static_cast<ParticleDupliWeight *>(
799 MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight"));
800 dw->ob = object;
801 dw->count = 1;
802 BLI_addtail(&part->instance_weights, dw);
803 }
804
805 dw->index = index++;
806 }
808
809 /* Ensure there is an element marked as current. */
810 int current = 0;
811 LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
812 if (dw->flag & PART_DUPLIW_CURRENT) {
813 current = 1;
814 break;
815 }
816 }
817
818 if (!current) {
819 dw = static_cast<ParticleDupliWeight *>(part->instance_weights.first);
820 if (dw) {
822 }
823 }
824}
825
831
832/************************************************/
833/* Freeing stuff */
834/************************************************/
835
837{
838 if (fluid) {
839 MEM_freeN(fluid);
840 }
841}
842
843void free_hair(Object *object, ParticleSystem *psys, int dynamics)
844{
846
848 {
849 MEM_SAFE_FREE(pa->hair);
850 pa->totkey = 0;
851 }
852
853 psys->flag &= ~PSYS_HAIR_DONE;
854
855 if (psys->clmd) {
856 if (dynamics) {
858 psys->clmd = nullptr;
859 PTCacheID pid;
860 BKE_ptcache_id_from_particles(&pid, object, psys);
862 }
863 else {
865 }
866 }
867
868 if (psys->hair_in_mesh) {
869 BKE_id_free(nullptr, psys->hair_in_mesh);
870 }
871 psys->hair_in_mesh = nullptr;
872
873 if (psys->hair_out_mesh) {
874 BKE_id_free(nullptr, psys->hair_out_mesh);
875 }
876 psys->hair_out_mesh = nullptr;
877}
879{
881
882 if (psys->part->type == PART_HAIR) {
883 return;
884 }
885
886 if (psys->particles && psys->particles->keys) {
887 MEM_freeN(psys->particles->keys);
888
890 {
891 if (pa->keys) {
892 pa->keys = nullptr;
893 pa->totkey = 0;
894 }
895 }
896 }
897}
899{
901 psys->childcache = nullptr;
902 psys->totchildcache = 0;
903}
905{
906 if (edit) {
908 edit->pathcache = nullptr;
909 edit->totcached = 0;
910 }
911 if (psys) {
913 psys->pathcache = nullptr;
914 psys->totcached = 0;
915
917 }
918}
920{
921 if (psys->child) {
922 MEM_freeN(psys->child);
923 psys->child = nullptr;
924 psys->totchild = 0;
925 }
926
928}
930{
932
933 if (psys->particles) {
934 /* Even though psys->part should never be nullptr,
935 * this can happen as an exception during deletion.
936 * See ID_REMAP_SKIP/FORCE/FLAG_NEVER_NULL_USAGE in BKE_library_remap. */
937 if (psys->part && psys->part->type == PART_HAIR) {
939 {
940 if (pa->hair) {
941 MEM_freeN(pa->hair);
942 }
943 }
944 }
945
946 if (psys->particles->keys) {
947 MEM_freeN(psys->particles->keys);
948 }
949
950 if (psys->particles->boid) {
951 MEM_freeN(psys->particles->boid);
952 }
953
954 MEM_freeN(psys->particles);
955 psys->particles = nullptr;
956 psys->totpart = 0;
957 }
958}
960{
961 if (psys->pdd) {
962 MEM_SAFE_FREE(psys->pdd->cdata);
963
964 MEM_SAFE_FREE(psys->pdd->vdata);
965
966 MEM_SAFE_FREE(psys->pdd->ndata);
967
968 MEM_SAFE_FREE(psys->pdd->vedata);
969
970 psys->pdd->totpoint = 0;
971 psys->pdd->totpart = 0;
972 psys->pdd->partsize = 0;
973 }
974}
976{
977 if (psys) {
978 int nr = 0;
979
980 psys_free_path_cache(psys, nullptr);
981
982 /* NOTE: We pass dynamics=0 to free_hair() to prevent it from doing an
983 * unneeded clear of the cache. But for historical reason that code path
984 * was only clearing cloth part of modifier data.
985 *
986 * Part of the story there is that particle evaluation is trying to not
987 * re-allocate thew ModifierData itself, and limits all allocations to
988 * the cloth part of it.
989 *
990 * Why evaluation is relying on hair_free() and in some specific code
991 * paths there is beyond me.
992 */
993 free_hair(ob, psys, 0);
994 if (psys->clmd != nullptr) {
996 }
997
999
1000 if (psys->edit && psys->free_edit) {
1001 psys->free_edit(psys->edit);
1002 }
1003
1004 if (psys->child) {
1005 MEM_freeN(psys->child);
1006 psys->child = nullptr;
1007 psys->totchild = 0;
1008 }
1009
1010 /* check if we are last non-visible particle system */
1012 if (tpsys->part) {
1013 if (ELEM(tpsys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
1014 nr++;
1015 break;
1016 }
1017 }
1018 }
1019 /* clear do-not-draw-flag */
1020 if (!nr) {
1021 ob->transflag &= ~OB_DUPLIPARTS;
1022 }
1023
1024 psys->part = nullptr;
1025
1026 if ((psys->flag & PSYS_SHARED_CACHES) == 0) {
1028 }
1029 psys->pointcache = nullptr;
1030
1031 BLI_freelistN(&psys->targets);
1032
1034 BLI_kdtree_3d_free(psys->tree);
1035
1036 if (psys->fluid_springs) {
1037 MEM_freeN(psys->fluid_springs);
1038 }
1039
1041
1042 if (psys->pdd) {
1043 psys_free_pdd(psys);
1044 MEM_freeN(psys->pdd);
1045 }
1046
1048
1049 MEM_freeN(psys);
1050 }
1051}
1052
1054{
1055 /* Free existing particles. */
1056 if (psys_dst->particles != psys_src->particles) {
1057 psys_free_particles(psys_dst);
1058 }
1059 if (psys_dst->child != psys_src->child) {
1060 psys_free_children(psys_dst);
1061 }
1062 /* Restore counters. */
1063 psys_dst->totpart = psys_src->totpart;
1064 psys_dst->totchild = psys_src->totchild;
1065 /* Copy particles and children. */
1066 psys_dst->particles = static_cast<ParticleData *>(MEM_dupallocN(psys_src->particles));
1067 psys_dst->child = static_cast<ChildParticle *>(MEM_dupallocN(psys_src->child));
1068
1069 /* Ideally this should only be performed if `(psys_dst->part->type == PART_HAIR)`.
1070 *
1071 * But #ParticleData (`psys_dst`) is some sub-data of the #Object ID, while #ParticleSettings
1072 * (`psys_dst->part`) is another ID. In case the particle settings is a linked ID that gets
1073 * missing, it will be replaced (in readfile code) by a place-holder, which defaults to a
1074 * `PART_EMITTER` type of particle settings.
1075 *
1076 * This leads to a situation where each particle of `psys_dst` still has a valid allocated `hair`
1077 * data, which should still be preserved in case the missing particle settings ID becomes valid
1078 * again.
1079 *
1080 * Furthermore, #free_hair() always frees `pa->hair` if it's not nullptr, regardless of the
1081 * particle type. So *not* copying here would cause a double free (or more), e.g. freeing the
1082 * copy-on-evaluation copy and the original data will crash Blender.
1083 * In any case, sharing pointers between `psys_src` and `psys_dst` should be forbidden.
1084 *
1085 * So while we could in theory 'sanitize' the situation by setting `pa->hair` to nullptr in the
1086 * new copy (in case of non-`PART_HAIR` type), it is probably safer for now to systematically
1087 * duplicate the `hair` data if available. */
1088 {
1089 ParticleData *pa;
1090 int p;
1091 for (p = 0, pa = psys_dst->particles; p < psys_dst->totpart; p++, pa++) {
1092 pa->hair = static_cast<HairKey *>(MEM_dupallocN(pa->hair));
1093 }
1094 }
1095 if (psys_dst->particles && (psys_dst->particles->keys || psys_dst->particles->boid)) {
1096 ParticleKey *key = psys_dst->particles->keys;
1097 BoidParticle *boid = psys_dst->particles->boid;
1098 ParticleData *pa;
1099 int p;
1100 if (key != nullptr) {
1101 key = static_cast<ParticleKey *>(MEM_dupallocN(key));
1102 }
1103 if (boid != nullptr) {
1104 boid = static_cast<BoidParticle *>(MEM_dupallocN(boid));
1105 }
1106 for (p = 0, pa = psys_dst->particles; p < psys_dst->totpart; p++, pa++) {
1107 if (boid != nullptr) {
1108 pa->boid = boid++;
1109 }
1110 if (key != nullptr) {
1111 pa->keys = key;
1112 key += pa->totkey;
1113 }
1114 }
1115 }
1116}
1117
1118/************************************************/
1119/* Interpolation */
1120/************************************************/
1121
1123 float v1, float v2, float v3, float v4, const float w[4], int four)
1124{
1125 float value;
1126
1127 value = w[0] * v1 + w[1] * v2 + w[2] * v3;
1128 if (four) {
1129 value += w[3] * v4;
1130 }
1131
1132 CLAMP(value, 0.0f, 1.0f);
1133
1134 return value;
1135}
1136
1138 short type, ParticleKey keys[4], float dt, ParticleKey *result, bool velocity)
1139{
1140 float t[4];
1141
1142 if (type < 0) {
1143 interp_cubic_v3(result->co, result->vel, keys[1].co, keys[1].vel, keys[2].co, keys[2].vel, dt);
1144 }
1145 else {
1146 key_curve_position_weights(dt, t, type);
1147
1148 interp_v3_v3v3v3v3(result->co, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
1149
1150 if (velocity) {
1151 float temp[3];
1152
1153 if (dt > 0.999f) {
1154 key_curve_position_weights(dt - 0.001f, t, type);
1155 interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
1156 sub_v3_v3v3(result->vel, result->co, temp);
1157 }
1158 else {
1159 key_curve_position_weights(dt + 0.001f, t, type);
1160 interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
1161 sub_v3_v3v3(result->vel, temp, result->co);
1162 }
1163 }
1164 }
1165}
1166
1194 PointCache *cache,
1195 PTCacheMem **cur,
1196 int index,
1197 float t,
1198 ParticleKey *key1,
1199 ParticleKey *key2)
1200{
1201 static PTCacheMem *pm = nullptr;
1202 int index1, index2;
1203
1204 if (index < 0) { /* initialize */
1205 *cur = static_cast<PTCacheMem *>(cache->mem_cache.first);
1206
1207 if (*cur) {
1208 *cur = (*cur)->next;
1209 }
1210 }
1211 else {
1212 if (*cur) {
1213 while (*cur && (*cur)->next && float((*cur)->frame) < t) {
1214 *cur = (*cur)->next;
1215 }
1216
1217 pm = *cur;
1218
1219 index2 = BKE_ptcache_mem_index_find(pm, index);
1220 index1 = BKE_ptcache_mem_index_find(pm->prev, index);
1221 if (index2 < 0) {
1222 return;
1223 }
1224
1225 BKE_ptcache_make_particle_key(key2, index2, pm->data, float(pm->frame));
1226 if (index1 < 0) {
1227 copy_particle_key(key1, key2, 1);
1228 }
1229 else {
1230 BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, float(pm->prev->frame));
1231 }
1232 }
1233 else if (cache->mem_cache.first) {
1234 pm = static_cast<PTCacheMem *>(cache->mem_cache.first);
1235 index2 = BKE_ptcache_mem_index_find(pm, index);
1236 if (index2 < 0) {
1237 return;
1238 }
1239 BKE_ptcache_make_particle_key(key2, index2, pm->data, float(pm->frame));
1240 copy_particle_key(key1, key2, 1);
1241 }
1242 }
1243}
1245 int index,
1246 float *r_start,
1247 float *r_dietime)
1248{
1249 int ret = 0;
1250
1251 LISTBASE_FOREACH (PTCacheMem *, pm, &cache->mem_cache) {
1252 if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
1253 *r_start = pm->frame;
1254 ret++;
1255 break;
1256 }
1257 }
1258
1260 if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
1261 /* Die *after* the last available frame. */
1262 *r_dietime = pm->frame + 1;
1263 ret++;
1264 break;
1265 }
1266 }
1267
1268 return ret == 2;
1269}
1270
1272{
1273 int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */
1274
1276 if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
1277 /* Die *after* the last available frame. */
1278 dietime = pm->frame + 1;
1279 break;
1280 }
1281 }
1282
1283 return float(dietime);
1284}
1285
1287 ParticleSystem *psys,
1288 ParticleData *pa,
1290{
1291
1292 if (pind->epoint) {
1293 PTCacheEditPoint *point = pind->epoint;
1294
1295 pind->ekey[0] = point->keys;
1296 pind->ekey[1] = point->totkey > 1 ? point->keys + 1 : nullptr;
1297
1298 pind->birthtime = *(point->keys->time);
1299 pind->dietime = *((point->keys + point->totkey - 1)->time);
1300 }
1301 else if (pind->keyed) {
1302 ParticleKey *key = pa->keys;
1303 pind->kkey[0] = key;
1304 pind->kkey[1] = pa->totkey > 1 ? key + 1 : nullptr;
1305
1306 pind->birthtime = key->time;
1307 pind->dietime = (key + pa->totkey - 1)->time;
1308 }
1309 else if (pind->cache) {
1310 float start = 0.0f, dietime = 0.0f;
1311 get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, nullptr, nullptr);
1312 pind->birthtime = pa ? pa->time : pind->cache->startframe;
1313 pind->dietime = pa ? pa->dietime : (pind->cache->endframe + 1);
1314
1315 if (get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &dietime)) {
1316 pind->birthtime = std::max(pind->birthtime, start);
1317 pind->dietime = std::min(pind->dietime, dietime);
1318 }
1319 }
1320 else {
1321 HairKey *key = pa->hair;
1322 pind->hkey[0] = key;
1323 pind->hkey[1] = key + 1;
1324
1325 pind->birthtime = key->time;
1326 pind->dietime = (key + pa->totkey - 1)->time;
1327
1328 if (pind->mesh) {
1329 float3 *positions = pind->mesh->vert_positions_for_write().data();
1330 pind->vert_positions[0] = &positions[pa->hair_index];
1331 pind->vert_positions[1] = pind->vert_positions[0] + 1;
1332 }
1333 }
1334}
1336{
1337 copy_v3_v3(key->co, ekey->co);
1338 if (ekey->vel) {
1339 copy_v3_v3(key->vel, ekey->vel);
1340 }
1341 key->time = *(ekey->time);
1342}
1343static void hair_to_particle(ParticleKey *key, HairKey *hkey)
1344{
1345 copy_v3_v3(key->co, hkey->co);
1346 key->time = hkey->time;
1347}
1348
1349static void mvert_to_particle(ParticleKey *key, float3 *position, HairKey *hkey)
1350{
1351 copy_v3_v3(key->co, *position);
1352 key->time = hkey->time;
1353}
1354
1356 int p,
1357 ParticleData *pa,
1358 float t,
1360 ParticleKey *result)
1361{
1362 PTCacheEditPoint *point = pind->epoint;
1363 ParticleKey keys[4];
1364 int point_vel = (point && point->keys->vel);
1365 float real_t, dfra, keytime, invdt = 1.0f;
1366
1367 /* billboards won't fill in all of these, so start cleared */
1368 memset(keys, 0, sizeof(keys));
1369
1370 /* interpret timing and find keys */
1371 if (point) {
1372 if (result->time < 0.0f) {
1373 real_t = -result->time;
1374 }
1375 else {
1376 real_t = *(pind->ekey[0]->time) +
1377 t * (*(pind->ekey[0][point->totkey - 1].time) - *(pind->ekey[0]->time));
1378 }
1379
1380 while (*(pind->ekey[1]->time) < real_t) {
1381 pind->ekey[1]++;
1382 }
1383
1384 pind->ekey[0] = pind->ekey[1] - 1;
1385 }
1386 else if (pind->keyed) {
1387 /* we have only one key, so let's use that */
1388 if (pind->kkey[1] == nullptr) {
1389 copy_particle_key(result, pind->kkey[0], 1);
1390 return;
1391 }
1392
1393 if (result->time < 0.0f) {
1394 real_t = -result->time;
1395 }
1396 else {
1397 real_t = pind->kkey[0]->time +
1398 t * (pind->kkey[0][pa->totkey - 1].time - pind->kkey[0]->time);
1399 }
1400
1401 if (psys->part->phystype == PART_PHYS_KEYED && psys->flag & PSYS_KEYED_TIMING) {
1402 ParticleTarget *pt = static_cast<ParticleTarget *>(psys->targets.first);
1403
1404 pt = pt->next;
1405
1406 while (pt && pa->time + pt->time < real_t) {
1407 pt = pt->next;
1408 }
1409
1410 if (pt) {
1411 pt = pt->prev;
1412
1413 if (pa->time + pt->time + pt->duration > real_t) {
1414 real_t = pa->time + pt->time;
1415 }
1416 }
1417 else {
1418 real_t = pa->time + ((ParticleTarget *)psys->targets.last)->time;
1419 }
1420 }
1421
1422 CLAMP(real_t, pa->time, pa->dietime);
1423
1424 while (pind->kkey[1]->time < real_t) {
1425 pind->kkey[1]++;
1426 }
1427
1428 pind->kkey[0] = pind->kkey[1] - 1;
1429 }
1430 else if (pind->cache) {
1431 if (result->time < 0.0f) { /* flag for time in frames */
1432 real_t = -result->time;
1433 }
1434 else {
1435 real_t = pa->time + t * (pa->dietime - pa->time);
1436 }
1437 }
1438 else {
1439 if (result->time < 0.0f) {
1440 real_t = -result->time;
1441 }
1442 else {
1443 real_t = pind->hkey[0]->time +
1444 t * (pind->hkey[0][pa->totkey - 1].time - pind->hkey[0]->time);
1445 }
1446
1447 while (pind->hkey[1]->time < real_t) {
1448 pind->hkey[1]++;
1449 pind->vert_positions[1]++;
1450 }
1451
1452 pind->hkey[0] = pind->hkey[1] - 1;
1453 }
1454
1455 /* set actual interpolation keys */
1456 if (point) {
1457 edit_to_particle(keys + 1, pind->ekey[0]);
1458 edit_to_particle(keys + 2, pind->ekey[1]);
1459 }
1460 else if (pind->mesh) {
1461 pind->vert_positions[0] = pind->vert_positions[1] - 1;
1462 mvert_to_particle(keys + 1, pind->vert_positions[0], pind->hkey[0]);
1463 mvert_to_particle(keys + 2, pind->vert_positions[1], pind->hkey[1]);
1464 }
1465 else if (pind->keyed) {
1466 memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey));
1467 memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey));
1468 }
1469 else if (pind->cache) {
1470 get_pointcache_keys_for_time(nullptr, pind->cache, &pind->pm, p, real_t, keys + 1, keys + 2);
1471 }
1472 else {
1473 hair_to_particle(keys + 1, pind->hkey[0]);
1474 hair_to_particle(keys + 2, pind->hkey[1]);
1475 }
1476
1477 /* set secondary interpolation keys for hair */
1478 if (!pind->keyed && !pind->cache && !point_vel) {
1479 if (point) {
1480 if (pind->ekey[0] != point->keys) {
1481 edit_to_particle(keys, pind->ekey[0] - 1);
1482 }
1483 else {
1484 edit_to_particle(keys, pind->ekey[0]);
1485 }
1486 }
1487 else if (pind->mesh) {
1488 if (pind->hkey[0] != pa->hair) {
1489 mvert_to_particle(keys, pind->vert_positions[0] - 1, pind->hkey[0] - 1);
1490 }
1491 else {
1492 mvert_to_particle(keys, pind->vert_positions[0], pind->hkey[0]);
1493 }
1494 }
1495 else {
1496 if (pind->hkey[0] != pa->hair) {
1497 hair_to_particle(keys, pind->hkey[0] - 1);
1498 }
1499 else {
1500 hair_to_particle(keys, pind->hkey[0]);
1501 }
1502 }
1503
1504 if (point) {
1505 if (pind->ekey[1] != point->keys + point->totkey - 1) {
1506 edit_to_particle(keys + 3, pind->ekey[1] + 1);
1507 }
1508 else {
1509 edit_to_particle(keys + 3, pind->ekey[1]);
1510 }
1511 }
1512 else if (pind->mesh) {
1513 if (pind->hkey[1] != pa->hair + pa->totkey - 1) {
1514 mvert_to_particle(keys + 3, pind->vert_positions[1] + 1, pind->hkey[1] + 1);
1515 }
1516 else {
1517 mvert_to_particle(keys + 3, pind->vert_positions[1], pind->hkey[1]);
1518 }
1519 }
1520 else {
1521 if (pind->hkey[1] != pa->hair + pa->totkey - 1) {
1522 hair_to_particle(keys + 3, pind->hkey[1] + 1);
1523 }
1524 else {
1525 hair_to_particle(keys + 3, pind->hkey[1]);
1526 }
1527 }
1528 }
1529
1530 dfra = keys[2].time - keys[1].time;
1531 keytime = (real_t - keys[1].time) / dfra;
1532
1533 /* Convert velocity to time-step size. */
1534 if (pind->keyed || pind->cache || point_vel) {
1535 invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.0f);
1536 mul_v3_fl(keys[1].vel, invdt);
1537 mul_v3_fl(keys[2].vel, invdt);
1538 interp_qt_qtqt(result->rot, keys[1].rot, keys[2].rot, keytime);
1539 }
1540
1541 /* Now we should have in chronological order k1<=k2<=t<=k3<=k4 with key-time between
1542 * [0, 1]->[k2, k3] (k1 & k4 used for cardinal & b-spline interpolation). */
1543 psys_interpolate_particle((pind->keyed || pind->cache || point_vel) ?
1544 -1 /* signal for cubic interpolation */
1545 :
1546 (pind->bspline ? KEY_BSPLINE : KEY_CARDINAL),
1547 keys,
1548 keytime,
1549 result,
1550 true);
1551
1552 /* the velocity needs to be converted back from cubic interpolation */
1553 if (pind->keyed || pind->cache || point_vel) {
1554 mul_v3_fl(result->vel, 1.0f / invdt);
1555 }
1556}
1557
1558static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCacheKey *result)
1559{
1560 int i = 0;
1561 ParticleCacheKey *cur = first;
1562
1563 /* scale the requested time to fit the entire path even if the path is cut early */
1564 t *= (first + first->segments)->time;
1565
1566 while (i < first->segments && cur->time < t) {
1567 cur++;
1568 }
1569
1570 if (cur->time == t) {
1571 *result = *cur;
1572 }
1573 else {
1574 float dt = (t - (cur - 1)->time) / (cur->time - (cur - 1)->time);
1575 interp_v3_v3v3(result->co, (cur - 1)->co, cur->co, dt);
1576 interp_v3_v3v3(result->vel, (cur - 1)->vel, cur->vel, dt);
1577 interp_qt_qtqt(result->rot, (cur - 1)->rot, cur->rot, dt);
1578 result->time = t;
1579 }
1580
1581 /* first is actual base rotation, others are incremental from first */
1582 if (cur == first || cur - 1 == first) {
1583 copy_qt_qt(result->rot, first->rot);
1584 }
1585 else {
1586 mul_qt_qtqt(result->rot, first->rot, result->rot);
1587 }
1588}
1589
1590/************************************************/
1591/* Particles on a dm */
1592/************************************************/
1593
1595 const float (*vert_positions)[3],
1596 const float (*vert_normals)[3],
1597 const MFace *mface,
1598 MTFace *tface,
1599 const float (*orcodata)[3],
1600 float w[4],
1601 float vec[3],
1602 float nor[3],
1603 float utan[3],
1604 float vtan[3],
1605 float orco[3])
1606{
1607 const float *v1 = nullptr, *v2 = nullptr, *v3 = nullptr, *v4 = nullptr;
1608 float e1[3], e2[3], s1, s2, t1, t2;
1609 float *uv1, *uv2, *uv3, *uv4;
1610 float n1[3], n2[3], n3[3], n4[3];
1611 float tuv[4][2];
1612 const float *o1, *o2, *o3, *o4;
1613
1614 v1 = vert_positions[mface->v1];
1615 v2 = vert_positions[mface->v2];
1616 v3 = vert_positions[mface->v3];
1617
1618 copy_v3_v3(n1, vert_normals[mface->v1]);
1619 copy_v3_v3(n2, vert_normals[mface->v2]);
1620 copy_v3_v3(n3, vert_normals[mface->v3]);
1621
1622 if (mface->v4) {
1623 v4 = vert_positions[mface->v4];
1624 copy_v3_v3(n4, vert_normals[mface->v4]);
1625
1626 interp_v3_v3v3v3v3(vec, v1, v2, v3, v4, w);
1627
1628 if (nor) {
1629 if (mface->flag & ME_SMOOTH) {
1630 interp_v3_v3v3v3v3(nor, n1, n2, n3, n4, w);
1631 }
1632 else {
1633 normal_quad_v3(nor, v1, v2, v3, v4);
1634 }
1635 }
1636 }
1637 else {
1638 interp_v3_v3v3v3(vec, v1, v2, v3, w);
1639
1640 if (nor) {
1641 if (mface->flag & ME_SMOOTH) {
1642 interp_v3_v3v3v3(nor, n1, n2, n3, w);
1643 }
1644 else {
1645 normal_tri_v3(nor, v1, v2, v3);
1646 }
1647 }
1648 }
1649
1650 /* calculate tangent vectors */
1651 if (utan && vtan) {
1652 if (tface) {
1653 uv1 = tface->uv[0];
1654 uv2 = tface->uv[1];
1655 uv3 = tface->uv[2];
1656 uv4 = tface->uv[3];
1657 }
1658 else {
1659 uv1 = tuv[0];
1660 uv2 = tuv[1];
1661 uv3 = tuv[2];
1662 uv4 = tuv[3];
1663 map_to_sphere(uv1, uv1 + 1, v1[0], v1[1], v1[2]);
1664 map_to_sphere(uv2, uv2 + 1, v2[0], v2[1], v2[2]);
1665 map_to_sphere(uv3, uv3 + 1, v3[0], v3[1], v3[2]);
1666 if (v4) {
1667 map_to_sphere(uv4, uv4 + 1, v4[0], v4[1], v4[2]);
1668 }
1669 }
1670
1671 if (v4) {
1672 s1 = uv3[0] - uv1[0];
1673 s2 = uv4[0] - uv1[0];
1674
1675 t1 = uv3[1] - uv1[1];
1676 t2 = uv4[1] - uv1[1];
1677
1678 sub_v3_v3v3(e1, v3, v1);
1679 sub_v3_v3v3(e2, v4, v1);
1680 }
1681 else {
1682 s1 = uv2[0] - uv1[0];
1683 s2 = uv3[0] - uv1[0];
1684
1685 t1 = uv2[1] - uv1[1];
1686 t2 = uv3[1] - uv1[1];
1687
1688 sub_v3_v3v3(e1, v2, v1);
1689 sub_v3_v3v3(e2, v3, v1);
1690 }
1691
1692 vtan[0] = (s1 * e2[0] - s2 * e1[0]);
1693 vtan[1] = (s1 * e2[1] - s2 * e1[1]);
1694 vtan[2] = (s1 * e2[2] - s2 * e1[2]);
1695
1696 utan[0] = (t1 * e2[0] - t2 * e1[0]);
1697 utan[1] = (t1 * e2[1] - t2 * e1[1]);
1698 utan[2] = (t1 * e2[2] - t2 * e1[2]);
1699 }
1700
1701 if (orco) {
1702 if (orcodata) {
1703 o1 = orcodata[mface->v1];
1704 o2 = orcodata[mface->v2];
1705 o3 = orcodata[mface->v3];
1706
1707 if (mface->v4) {
1708 o4 = orcodata[mface->v4];
1709
1710 interp_v3_v3v3v3v3(orco, o1, o2, o3, o4, w);
1711 }
1712 else {
1713 interp_v3_v3v3v3(orco, o1, o2, o3, w);
1714 }
1715 BKE_mesh_orco_verts_transform(mesh, (float(*)[3])orco, 1, true);
1716 }
1717 else {
1718 copy_v3_v3(orco, vec);
1719 }
1720 }
1721}
1722void psys_interpolate_uvs(const MTFace *tface, int quad, const float w[4], float uvco[2])
1723{
1724 float v10 = tface->uv[0][0];
1725 float v11 = tface->uv[0][1];
1726 float v20 = tface->uv[1][0];
1727 float v21 = tface->uv[1][1];
1728 float v30 = tface->uv[2][0];
1729 float v31 = tface->uv[2][1];
1730 float v40, v41;
1731
1732 if (quad) {
1733 v40 = tface->uv[3][0];
1734 v41 = tface->uv[3][1];
1735
1736 uvco[0] = w[0] * v10 + w[1] * v20 + w[2] * v30 + w[3] * v40;
1737 uvco[1] = w[0] * v11 + w[1] * v21 + w[2] * v31 + w[3] * v41;
1738 }
1739 else {
1740 uvco[0] = w[0] * v10 + w[1] * v20 + w[2] * v30;
1741 uvco[1] = w[0] * v11 + w[1] * v21 + w[2] * v31;
1742 }
1743}
1744
1745void psys_interpolate_mcol(const MCol *mcol, int quad, const float w[4], MCol *mc)
1746{
1747 const char *cp1, *cp2, *cp3, *cp4;
1748 char *cp;
1749
1750 cp = (char *)mc;
1751 cp1 = (const char *)&mcol[0];
1752 cp2 = (const char *)&mcol[1];
1753 cp3 = (const char *)&mcol[2];
1754
1755 if (quad) {
1756 cp4 = (char *)&mcol[3];
1757
1758 cp[0] = int(w[0] * cp1[0] + w[1] * cp2[0] + w[2] * cp3[0] + w[3] * cp4[0]);
1759 cp[1] = int(w[0] * cp1[1] + w[1] * cp2[1] + w[2] * cp3[1] + w[3] * cp4[1]);
1760 cp[2] = int(w[0] * cp1[2] + w[1] * cp2[2] + w[2] * cp3[2] + w[3] * cp4[2]);
1761 cp[3] = int(w[0] * cp1[3] + w[1] * cp2[3] + w[2] * cp3[3] + w[3] * cp4[3]);
1762 }
1763 else {
1764 cp[0] = int(w[0] * cp1[0] + w[1] * cp2[0] + w[2] * cp3[0]);
1765 cp[1] = int(w[0] * cp1[1] + w[1] * cp2[1] + w[2] * cp3[1]);
1766 cp[2] = int(w[0] * cp1[2] + w[1] * cp2[2] + w[2] * cp3[2]);
1767 cp[3] = int(w[0] * cp1[3] + w[1] * cp2[3] + w[2] * cp3[3]);
1768 }
1769}
1770
1772 Mesh *mesh, short from, int index, const float fw[4], const float *values)
1773{
1774 if (values == nullptr || index == -1) {
1775 return 0.0;
1776 }
1777
1778 switch (from) {
1779 case PART_FROM_VERT:
1780 return values[index];
1781 case PART_FROM_FACE:
1782 case PART_FROM_VOLUME: {
1783 MFace *mfaces = static_cast<MFace *>(
1784 CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy));
1785 MFace *mf = &mfaces[index];
1787 values[mf->v1], values[mf->v2], values[mf->v3], values[mf->v4], fw, mf->v4);
1788 }
1789 }
1790 return 0.0f;
1791}
1792
1793/* conversion of pa->fw to origspace layer coordinates */
1794static void psys_w_to_origspace(const float w[4], float uv[2])
1795{
1796 uv[0] = w[1] + w[2];
1797 uv[1] = w[2] + w[3];
1798}
1799
1800/* conversion of pa->fw to weights in face from origspace */
1801static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4], float neww[4])
1802{
1803 float v[4][3], co[3];
1804
1805 v[0][0] = osface->uv[0][0];
1806 v[0][1] = osface->uv[0][1];
1807 v[0][2] = 0.0f;
1808 v[1][0] = osface->uv[1][0];
1809 v[1][1] = osface->uv[1][1];
1810 v[1][2] = 0.0f;
1811 v[2][0] = osface->uv[2][0];
1812 v[2][1] = osface->uv[2][1];
1813 v[2][2] = 0.0f;
1814
1816 co[2] = 0.0f;
1817
1818 if (quad) {
1819 v[3][0] = osface->uv[3][0];
1820 v[3][1] = osface->uv[3][1];
1821 v[3][2] = 0.0f;
1822 interp_weights_poly_v3(neww, v, 4, co);
1823 }
1824 else {
1825 interp_weights_poly_v3(neww, v, 3, co);
1826 neww[3] = 0.0f;
1827 }
1828}
1829
1831 Mesh *mesh_original,
1832 int findex_orig,
1833 const float fw[4],
1834 LinkNode **poly_nodes)
1835{
1836 MFace *mtessface_final;
1837 const OrigSpaceFace *osface_final;
1838 int pindex_orig;
1839 float uv[2];
1840 const float(*faceuv)[2];
1841
1842 const int *index_mf_to_mpoly_deformed = nullptr;
1843 const int *index_mf_to_mpoly = nullptr;
1844 const int *index_mp_to_orig = nullptr;
1845
1846 const int totface_final = mesh_final->totface_legacy;
1847 const int totface_deformed = mesh_original ? mesh_original->totface_legacy : totface_final;
1848
1849 if (ELEM(0, totface_final, totface_deformed)) {
1850 return DMCACHE_NOTFOUND;
1851 }
1852
1853 index_mf_to_mpoly = static_cast<const int *>(
1855 index_mp_to_orig = static_cast<const int *>(
1857 BLI_assert(index_mf_to_mpoly);
1858
1859 if (mesh_original) {
1860 index_mf_to_mpoly_deformed = static_cast<const int *>(
1862 }
1863 else {
1864 BLI_assert(mesh_final->runtime->deformed_only);
1865 index_mf_to_mpoly_deformed = index_mf_to_mpoly;
1866 }
1867 BLI_assert(index_mf_to_mpoly_deformed);
1868
1869 pindex_orig = index_mf_to_mpoly_deformed[findex_orig];
1870
1871 if (mesh_original == nullptr) {
1872 mesh_original = mesh_final;
1873 }
1874
1875 index_mf_to_mpoly_deformed = nullptr;
1876
1877 mtessface_final = static_cast<MFace *>(CustomData_get_layer_for_write(
1878 &mesh_final->fdata_legacy, CD_MFACE, mesh_final->totface_legacy));
1879 osface_final = static_cast<OrigSpaceFace *>(CustomData_get_layer_for_write(
1880 &mesh_final->fdata_legacy, CD_ORIGSPACE, mesh_final->totface_legacy));
1881
1882 if (osface_final == nullptr) {
1883 /* Assume we don't need osface_final data, and we get a direct 1-1 mapping... */
1884 if (findex_orig < totface_final) {
1885 // printf("\tNO CD_ORIGSPACE, assuming not needed\n");
1886 return findex_orig;
1887 }
1888
1889 printf("\tNO CD_ORIGSPACE, error out of range\n");
1890 return DMCACHE_NOTFOUND;
1891 }
1892 if (findex_orig >= mesh_original->totface_legacy) {
1893 return DMCACHE_NOTFOUND; /* index not in the original mesh */
1894 }
1895
1896 psys_w_to_origspace(fw, uv);
1897
1898 if (poly_nodes) {
1899 /* we can have a restricted linked list of faces to check, faster! */
1900 LinkNode *tessface_node = poly_nodes[pindex_orig];
1901
1902 for (; tessface_node; tessface_node = tessface_node->next) {
1903 int findex_dst = POINTER_AS_INT(tessface_node->link);
1904 faceuv = osface_final[findex_dst].uv;
1905
1906 /* check that this intersects - Its possible this misses :/ -
1907 * could also check its not between */
1908 if (mtessface_final[findex_dst].v4) {
1909 if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
1910 return findex_dst;
1911 }
1912 }
1913 else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
1914 return findex_dst;
1915 }
1916 }
1917 }
1918 else { /* if we have no node, try every face */
1919 for (int findex_dst = 0; findex_dst < totface_final; findex_dst++) {
1920 /* If current tessface from 'final' DM and orig tessface (given by index)
1921 * map to the same orig poly. */
1922 if (BKE_mesh_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex_dst) ==
1923 pindex_orig)
1924 {
1925 faceuv = osface_final[findex_dst].uv;
1926
1927 /* check that this intersects - Its possible this misses :/ -
1928 * could also check its not between */
1929 if (mtessface_final[findex_dst].v4) {
1930 if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
1931 return findex_dst;
1932 }
1933 }
1934 else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
1935 return findex_dst;
1936 }
1937 }
1938 }
1939 }
1940
1941 return DMCACHE_NOTFOUND;
1942}
1943
1945 int from,
1946 int index,
1947 int index_dmcache,
1948 const float fw[4],
1949 float /*foffset*/,
1950 int *mapindex,
1951 float mapfw[4])
1952{
1953 if (index < 0) {
1954 return 0;
1955 }
1956
1957 if (mesh->runtime->deformed_only || index_dmcache == DMCACHE_ISCHILD) {
1958 /* for meshes that are either only deformed or for child particles, the
1959 * index and fw do not require any mapping, so we can directly use it */
1960 if (from == PART_FROM_VERT) {
1961 if (index >= mesh->verts_num) {
1962 return 0;
1963 }
1964
1965 *mapindex = index;
1966 }
1967 else { /* FROM_FACE/FROM_VOLUME */
1968 if (index >= mesh->totface_legacy) {
1969 return 0;
1970 }
1971
1972 *mapindex = index;
1973 copy_v4_v4(mapfw, fw);
1974 }
1975 }
1976 else {
1977 /* for other meshes that have been modified, we try to map the particle
1978 * to their new location, which means a different index, and for faces
1979 * also a new face interpolation weights */
1980 if (from == PART_FROM_VERT) {
1981 if (index_dmcache == DMCACHE_NOTFOUND || index_dmcache >= mesh->verts_num) {
1982 return 0;
1983 }
1984
1985 *mapindex = index_dmcache;
1986 }
1987 else { /* FROM_FACE/FROM_VOLUME */
1988 /* find a face on the derived mesh that uses this face */
1989 int i = index_dmcache;
1990
1991 if (i == DMCACHE_NOTFOUND || i >= mesh->totface_legacy) {
1992 return 0;
1993 }
1994
1995 *mapindex = i;
1996
1997 /* modify the original weights to become
1998 * weights for the derived mesh face */
1999 OrigSpaceFace *osface = static_cast<OrigSpaceFace *>(
2000 CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_ORIGSPACE, mesh->totface_legacy));
2001 const MFace *mfaces = static_cast<const MFace *>(
2002 CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE));
2003 const MFace *mface = &mfaces[i];
2004
2005 if (osface == nullptr) {
2006 mapfw[0] = mapfw[1] = mapfw[2] = mapfw[3] = 0.0f;
2007 }
2008 else {
2009 psys_origspace_to_w(&osface[i], mface->v4, fw, mapfw);
2010 }
2011 }
2012 }
2013
2014 return 1;
2015}
2016
2017void psys_particle_on_dm(Mesh *mesh_final,
2018 int from,
2019 int index,
2020 int index_dmcache,
2021 const float fw[4],
2022 float foffset,
2023 float vec[3],
2024 float nor[3],
2025 float utan[3],
2026 float vtan[3],
2027 float orco[3])
2028{
2029 float tmpnor[3], mapfw[4];
2030 const float(*orcodata)[3];
2031 int mapindex;
2032
2033 if (!psys_map_index_on_dm(mesh_final, from, index, index_dmcache, fw, foffset, &mapindex, mapfw))
2034 {
2035 if (vec) {
2036 vec[0] = vec[1] = vec[2] = 0.0;
2037 }
2038 if (nor) {
2039 nor[0] = nor[1] = 0.0;
2040 nor[2] = 1.0;
2041 }
2042 if (orco) {
2043 orco[0] = orco[1] = orco[2] = 0.0;
2044 }
2045 if (utan) {
2046 utan[0] = utan[1] = utan[2] = 0.0;
2047 }
2048 if (vtan) {
2049 vtan[0] = vtan[1] = vtan[2] = 0.0;
2050 }
2051
2052 return;
2053 }
2054
2055 orcodata = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh_final->vert_data, CD_ORCO));
2056 const blender::Span<blender::float3> vert_normals = mesh_final->vert_normals();
2057
2058 if (from == PART_FROM_VERT) {
2059 const blender::Span<blender::float3> vert_positions = mesh_final->vert_positions();
2060 copy_v3_v3(vec, vert_positions[mapindex]);
2061
2062 if (nor) {
2063 copy_v3_v3(nor, vert_normals[mapindex]);
2064 }
2065
2066 if (orco) {
2067 if (orcodata) {
2068 copy_v3_v3(orco, orcodata[mapindex]);
2069 BKE_mesh_orco_verts_transform(mesh_final, (float(*)[3])orco, 1, true);
2070 }
2071 else {
2072 copy_v3_v3(orco, vec);
2073 }
2074 }
2075
2076 if (utan && vtan) {
2077 utan[0] = utan[1] = utan[2] = 0.0f;
2078 vtan[0] = vtan[1] = vtan[2] = 0.0f;
2079 }
2080 }
2081 else { /* PART_FROM_FACE / PART_FROM_VOLUME */
2082 MFace *mface;
2083 MTFace *mtface;
2084
2085 MFace *mfaces = static_cast<MFace *>(CustomData_get_layer_for_write(
2086 &mesh_final->fdata_legacy, CD_MFACE, mesh_final->totface_legacy));
2087 mface = &mfaces[mapindex];
2088 const blender::Span<blender::float3> vert_positions = mesh_final->vert_positions();
2089 mtface = static_cast<MTFace *>(CustomData_get_layer_for_write(
2090 &mesh_final->fdata_legacy, CD_MTFACE, mesh_final->totface_legacy));
2091
2092 if (mtface) {
2093 mtface += mapindex;
2094 }
2095
2096 if (from == PART_FROM_VOLUME) {
2097 psys_interpolate_face(mesh_final,
2098 reinterpret_cast<const float(*)[3]>(vert_positions.data()),
2099 reinterpret_cast<const float(*)[3]>(vert_normals.data()),
2100 mface,
2101 mtface,
2102 orcodata,
2103 mapfw,
2104 vec,
2105 tmpnor,
2106 utan,
2107 vtan,
2108 orco);
2109 if (nor) {
2110 copy_v3_v3(nor, tmpnor);
2111 }
2112
2113 /* XXX Why not normalize tmpnor before copying it into nor??? -- mont29 */
2114 normalize_v3(tmpnor);
2115
2116 mul_v3_fl(tmpnor, -foffset);
2117 add_v3_v3(vec, tmpnor);
2118 }
2119 else {
2120 psys_interpolate_face(mesh_final,
2121 reinterpret_cast<const float(*)[3]>(vert_positions.data()),
2122 reinterpret_cast<const float(*)[3]>(vert_normals.data()),
2123 mface,
2124 mtface,
2125 orcodata,
2126 mapfw,
2127 vec,
2128 nor,
2129 utan,
2130 vtan,
2131 orco);
2132 }
2133 }
2134}
2135
2136float psys_particle_value_from_verts(Mesh *mesh, short from, ParticleData *pa, float *values)
2137{
2138 float mapfw[4];
2139 int mapindex;
2140
2142 mesh, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, &mapindex, mapfw))
2143 {
2144 return 0.0f;
2145 }
2146
2147 return psys_interpolate_value_from_verts(mesh, from, mapindex, mapfw, values);
2148}
2149
2151{
2153
2155 if (md->type == eModifierType_ParticleSystem) {
2156 psmd = (ParticleSystemModifierData *)md;
2157 if (psmd->psys == psys) {
2158 return psmd;
2159 }
2160 }
2161 }
2162 return nullptr;
2163}
2164
2165/************************************************/
2166/* Particles on a shape */
2167/************************************************/
2168
2169/* ready for future use */
2170static void psys_particle_on_shape(int /*distr*/,
2171 int /*index*/,
2172 float * /*fuv*/,
2173 float vec[3],
2174 float nor[3],
2175 float utan[3],
2176 float vtan[3],
2177 float orco[3])
2178{
2179 /* TODO */
2180 const float zerovec[3] = {0.0f, 0.0f, 0.0f};
2181 if (vec) {
2182 copy_v3_v3(vec, zerovec);
2183 }
2184 if (nor) {
2185 copy_v3_v3(nor, zerovec);
2186 }
2187 if (utan) {
2188 copy_v3_v3(utan, zerovec);
2189 }
2190 if (vtan) {
2191 copy_v3_v3(vtan, zerovec);
2192 }
2193 if (orco) {
2194 copy_v3_v3(orco, zerovec);
2195 }
2196}
2197
2198/************************************************/
2199/* Particles on emitter */
2200/************************************************/
2201
2203{
2204 MTex *mtex;
2205 int i;
2206
2207 if (!psys->part) {
2208 return;
2209 }
2210
2211 for (i = 0; i < MAX_MTEX; i++) {
2212 mtex = psys->part->mtex[i];
2213 if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV)) {
2214 r_cddata_masks->fmask |= CD_MASK_MTFACE;
2215 }
2216 }
2217
2218 if (psys->part->tanfac != 0.0f) {
2219 r_cddata_masks->fmask |= CD_MASK_MTFACE;
2220 }
2221
2222 /* Ask for vertex-groups if we need them. */
2223 for (i = 0; i < PSYS_TOT_VG; i++) {
2224 if (psys->vgroup[i]) {
2225 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
2226 break;
2227 }
2228 }
2229
2230 /* particles only need this if they are after a non deform modifier, and
2231 * the modifier stack will only create them in that case. */
2232 r_cddata_masks->lmask |= CD_MASK_ORIGSPACE_MLOOP;
2233 /* XXX Check we do need all those? */
2234 r_cddata_masks->vmask |= CD_MASK_ORIGINDEX;
2235 r_cddata_masks->emask |= CD_MASK_ORIGINDEX;
2236 r_cddata_masks->pmask |= CD_MASK_ORIGINDEX;
2237
2238 r_cddata_masks->vmask |= CD_MASK_ORCO;
2239}
2240
2242 int from,
2243 int index,
2244 int index_dmcache,
2245 float fuv[4],
2246 float foffset,
2247 float vec[3],
2248 float nor[3],
2249 float utan[3],
2250 float vtan[3],
2251 float orco[3])
2252{
2253 if (psmd && psmd->mesh_final) {
2254 if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) {
2255 if (vec) {
2256 copy_v3_v3(vec, fuv);
2257 }
2258
2259 if (orco) {
2260 copy_v3_v3(orco, fuv);
2261 }
2262 return;
2263 }
2264 /* we can't use the num_dmcache */
2266 psmd->mesh_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco);
2267 }
2268 else {
2269 psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco);
2270 }
2271}
2272
2273/************************************************/
2274/* Path Cache */
2275/************************************************/
2276
2278{
2281 EffectorData efd;
2282 ParticleSystem *psys = sim->psys;
2283 EffectorWeights *weights = sim->psys->part->effector_weights;
2285 PARTICLE_P;
2286
2287 if (!effectors) {
2288 return;
2289 }
2290
2292 {
2294 sim->psys->part->from,
2295 pa->num,
2296 pa->num_dmcache,
2297 pa->fuv,
2298 pa->foffset,
2299 state.co,
2300 nullptr,
2301 nullptr,
2302 nullptr,
2303 nullptr);
2304
2305 mul_m4_v3(sim->ob->object_to_world().ptr(), state.co);
2306 mul_mat3_m4_v3(sim->ob->object_to_world().ptr(), state.vel);
2307
2308 pd_point_from_particle(sim, pa, &state, &point);
2309
2310 LISTBASE_FOREACH (EffectorCache *, eff, effectors) {
2311 if (eff->pd->forcefield != PFIELD_GUIDE) {
2312 continue;
2313 }
2314
2315 if (!eff->guide_data) {
2316 eff->guide_data = static_cast<GuideEffectorData *>(
2317 MEM_callocN(sizeof(GuideEffectorData) * psys->totpart, "GuideEffectorData"));
2318 }
2319
2320 data = eff->guide_data + p;
2321
2322 sub_v3_v3v3(efd.vec_to_point, state.co, eff->guide_loc);
2323 copy_v3_v3(efd.nor, eff->guide_dir);
2324 efd.distance = len_v3(efd.vec_to_point);
2325
2326 copy_v3_v3(data->vec_to_point, efd.vec_to_point);
2327 data->strength = effector_falloff(eff, &efd, &point, weights);
2328 }
2329 }
2330}
2331
2332bool do_guides(Depsgraph *depsgraph,
2333 ParticleSettings *part,
2334 ListBase *effectors,
2336 int index,
2337 float time)
2338{
2339 CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve :
2340 nullptr;
2341 CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve :
2342 nullptr;
2343 PartDeflect *pd;
2344 Curve *cu;
2346
2347 float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f};
2348 float guidevec[4], guidedir[3], rot2[4], temp[3];
2349 float guidetime, radius, weight, angle, totstrength = 0.0f;
2350 float vec_to_point[3];
2351
2352 if (effectors) {
2353 LISTBASE_FOREACH (EffectorCache *, eff, effectors) {
2354 pd = eff->pd;
2355
2356 if (pd->forcefield != PFIELD_GUIDE) {
2357 continue;
2358 }
2359
2360 data = eff->guide_data + index;
2361
2362 if (data->strength <= 0.0f) {
2363 continue;
2364 }
2365
2366 guidetime = time / (1.0f - pd->free_end);
2367
2368 if (guidetime > 1.0f) {
2369 continue;
2370 }
2371
2372 cu = (Curve *)eff->ob->data;
2373
2374 if (pd->flag & PFIELD_GUIDE_PATH_ADD) {
2375 if (BKE_where_on_path(eff->ob,
2376 data->strength * guidetime,
2377 guidevec,
2378 guidedir,
2379 nullptr,
2380 &radius,
2381 &weight) == 0)
2382 {
2383 return false;
2384 }
2385 }
2386 else {
2387 if (BKE_where_on_path(eff->ob, guidetime, guidevec, guidedir, nullptr, &radius, &weight) ==
2388 0)
2389 {
2390 return false;
2391 }
2392 }
2393
2394 mul_m4_v3(eff->ob->object_to_world().ptr(), guidevec);
2395 mul_mat3_m4_v3(eff->ob->object_to_world().ptr(), guidedir);
2396
2397 normalize_v3(guidedir);
2398
2399 copy_v3_v3(vec_to_point, data->vec_to_point);
2400
2401 if (guidetime != 0.0f) {
2402 /* curve direction */
2403 cross_v3_v3v3(temp, eff->guide_dir, guidedir);
2404 angle = dot_v3v3(eff->guide_dir, guidedir) / len_v3(eff->guide_dir);
2405 angle = safe_acosf(angle);
2406 axis_angle_to_quat(rot2, temp, angle);
2407 mul_qt_v3(rot2, vec_to_point);
2408
2409 /* curve tilt */
2410 axis_angle_to_quat(rot2, guidedir, guidevec[3] - eff->guide_loc[3]);
2411 mul_qt_v3(rot2, vec_to_point);
2412 }
2413
2414 /* curve taper */
2415 if (cu->taperobj) {
2416 mul_v3_fl(vec_to_point,
2418 eff->scene,
2419 cu->taperobj,
2420 int(data->strength * guidetime * 100.0f),
2421 100));
2422 }
2423 else { /* Curve size. */
2424 if (cu->flag & CU_PATH_RADIUS) {
2425 mul_v3_fl(vec_to_point, radius);
2426 }
2427 }
2428
2429 if (clumpcurve) {
2430 BKE_curvemapping_changed_all(clumpcurve);
2431 }
2432 if (roughcurve) {
2433 BKE_curvemapping_changed_all(roughcurve);
2434 }
2435
2436 {
2437 ParticleKey key;
2438 const float par_co[3] = {0.0f, 0.0f, 0.0f};
2439 const float par_vel[3] = {0.0f, 0.0f, 0.0f};
2440 const float par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
2441 const float orco_offset[3] = {0.0f, 0.0f, 0.0f};
2442
2443 copy_v3_v3(key.co, vec_to_point);
2444 do_kink(&key,
2445 par_co,
2446 par_vel,
2447 par_rot,
2448 guidetime,
2449 pd->kink_freq,
2450 pd->kink_shape,
2451 pd->kink_amp,
2452 0.0f,
2453 pd->kink,
2454 pd->kink_axis,
2455 nullptr,
2456 0);
2457 do_clump(&key,
2458 par_co,
2459 guidetime,
2460 orco_offset,
2461 pd->clump_fac,
2462 pd->clump_pow,
2463 1.0f,
2464 part->child_flag & PART_CHILD_USE_CLUMP_NOISE,
2465 part->clump_noise_size,
2466 clumpcurve);
2467 copy_v3_v3(vec_to_point, key.co);
2468 }
2469
2470 add_v3_v3(vec_to_point, guidevec);
2471
2472 // sub_v3_v3v3(pa_loc, pa_loc, pa_zero);
2473 madd_v3_v3fl(effect, vec_to_point, data->strength);
2474 madd_v3_v3fl(veffect, guidedir, data->strength);
2475 totstrength += data->strength;
2476
2477 if (pd->flag & PFIELD_GUIDE_PATH_WEIGHT) {
2478 totstrength *= weight;
2479 }
2480 }
2481 }
2482
2483 if (totstrength != 0.0f) {
2484 if (totstrength > 1.0f) {
2485 mul_v3_fl(effect, 1.0f / totstrength);
2486 }
2487 CLAMP(totstrength, 0.0f, 1.0f);
2488 // add_v3_v3(effect, pa_zero);
2489 interp_v3_v3v3(state->co, state->co, effect, totstrength);
2490
2491 normalize_v3(veffect);
2492 mul_v3_fl(veffect, len_v3(state->vel));
2493 copy_v3_v3(state->vel, veffect);
2494 return true;
2495 }
2496 return false;
2497}
2498
2500 int i,
2501 ParticleCacheKey *ca,
2502 int k,
2503 int steps,
2504 float * /*rootco*/,
2505 float effector,
2506 float /*dfra*/,
2507 float /*cfra*/,
2508 float *length,
2509 float *vec)
2510{
2511 float force[3] = {0.0f, 0.0f, 0.0f};
2512 ParticleKey eff_key;
2513 EffectedPoint epoint;
2514
2515 /* Don't apply effectors for dynamic hair, otherwise the effectors don't get applied twice. */
2516 if (sim->psys->flag & PSYS_HAIR_DYNAMICS) {
2517 return;
2518 }
2519
2520 copy_v3_v3(eff_key.co, (ca - 1)->co);
2521 copy_v3_v3(eff_key.vel, (ca - 1)->vel);
2522 copy_qt_qt(eff_key.rot, (ca - 1)->rot);
2523
2524 pd_point_from_particle(sim, sim->psys->particles + i, &eff_key, &epoint);
2526 sim->colliders,
2527 sim->psys->part->effector_weights,
2528 &epoint,
2529 force,
2530 nullptr,
2531 nullptr);
2532
2533 mul_v3_fl(force,
2534 effector * powf(float(k) / float(steps), 100.0f * sim->psys->part->eff_hair) /
2535 float(steps));
2536
2537 add_v3_v3(force, vec);
2538
2539 normalize_v3(force);
2540
2541 if (k < steps) {
2542 sub_v3_v3v3(vec, (ca + 1)->co, ca->co);
2543 }
2544
2545 madd_v3_v3v3fl(ca->co, (ca - 1)->co, force, *length);
2546
2547 if (k < steps) {
2548 *length = len_v3(vec);
2549 }
2550}
2552 ParticleKey *par,
2553 float *par_rot,
2554 ParticleKey *child,
2555 float flat,
2556 float radius)
2557{
2558 copy_v3_v3(child->co, cpa->fuv);
2559 mul_v3_fl(child->co, radius);
2560
2561 child->co[0] *= flat;
2562
2563 copy_v3_v3(child->vel, par->vel);
2564
2565 if (par_rot) {
2566 mul_qt_v3(par_rot, child->co);
2567 copy_qt_qt(child->rot, par_rot);
2568 }
2569 else {
2570 unit_qt(child->rot);
2571 }
2572
2573 add_v3_v3(child->co, par->co);
2574}
2575float *psys_cache_vgroup(Mesh *mesh, ParticleSystem *psys, int vgroup)
2576{
2577 float *vg = nullptr;
2578
2579 if (vgroup < 0) {
2580 /* hair dynamics pinning vgroup */
2581 }
2582 else if (psys->vgroup[vgroup]) {
2583 const MDeformVert *dvert = mesh->deform_verts().data();
2584 if (dvert) {
2585 int totvert = mesh->verts_num, i;
2586 vg = static_cast<float *>(MEM_callocN(sizeof(float) * totvert, "vg_cache"));
2587 if (psys->vg_neg & (1 << vgroup)) {
2588 for (i = 0; i < totvert; i++) {
2589 vg[i] = 1.0f - BKE_defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
2590 }
2591 }
2592 else {
2593 for (i = 0; i < totvert; i++) {
2594 vg[i] = BKE_defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
2595 }
2596 }
2597 }
2598 }
2599 return vg;
2600}
2601void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params)
2602{
2603 ParticleSystem *psys = sim->psys;
2604 ParticleSettings *part = sim->psys->part;
2605 KDTree_3d *tree;
2606 ChildParticle *cpa;
2607 ParticleTexture ptex;
2608 int p, totparent, totchild = sim->psys->totchild;
2609 float co[3], orco[3];
2610 int from = PART_FROM_FACE;
2611 totparent = int(totchild * part->parents * 0.3f);
2612
2613 if (use_render_params && part->child_percent && part->child_render_percent) {
2614 totparent *= float(part->child_percent) / float(part->child_render_percent);
2615 }
2616
2617 /* hard limit, workaround for it being ignored above */
2618 if (sim->psys->totpart < totparent) {
2619 totparent = sim->psys->totpart;
2620 }
2621
2622 tree = BLI_kdtree_3d_new(totparent);
2623
2624 for (p = 0, cpa = sim->psys->child; p < totparent; p++, cpa++) {
2626 from,
2627 cpa->num,
2629 cpa->fuv,
2630 cpa->foffset,
2631 co,
2632 nullptr,
2633 nullptr,
2634 nullptr,
2635 orco);
2636
2637 /* Check if particle doesn't exist because of texture influence.
2638 * Insert only existing particles into kdtree. */
2640 psys,
2641 part,
2642 psys->particles + cpa->pa[0],
2643 p,
2644 cpa->num,
2645 cpa->fuv,
2646 orco,
2647 &ptex,
2649 psys->cfra);
2650
2651 if (ptex.exist >= psys_frand(psys, p + 24)) {
2652 BLI_kdtree_3d_insert(tree, p, orco);
2653 }
2654 }
2655
2656 BLI_kdtree_3d_balance(tree);
2657
2658 for (; p < totchild; p++, cpa++) {
2660 from,
2661 cpa->num,
2663 cpa->fuv,
2664 cpa->foffset,
2665 co,
2666 nullptr,
2667 nullptr,
2668 nullptr,
2669 orco);
2670 cpa->parent = BLI_kdtree_3d_find_nearest(tree, orco, nullptr);
2671 }
2672
2673 BLI_kdtree_3d_free(tree);
2674}
2675
2678 Scene *scene,
2679 float cfra,
2680 const bool editupdate,
2681 const bool use_render_params)
2682{
2683 ParticleSystem *psys = sim->psys;
2684 ParticleSettings *part = psys->part;
2685 int totparent = 0, between = 0;
2686 int segments = 1 << part->draw_step;
2687 int totchild = psys->totchild;
2688
2689 psys_thread_context_init(ctx, sim);
2690
2691 /*---start figuring out what is actually wanted---*/
2692 if (psys_in_edit_mode(sim->depsgraph, psys)) {
2693 ParticleEditSettings *pset = &scene->toolsettings->particle;
2694
2695 if ((use_render_params == 0) &&
2696 (psys_orig_edit_get(psys) == nullptr || pset->flag & PE_DRAW_PART) == 0)
2697 {
2698 totchild = 0;
2699 }
2700
2701 segments = 1 << pset->draw_step;
2702 }
2703
2704 if (totchild && part->childtype == PART_CHILD_FACES) {
2705 totparent = int(totchild * part->parents * 0.3f);
2706
2707 if (use_render_params && part->child_percent && part->child_render_percent) {
2708 totparent *= float(part->child_percent) / float(part->child_render_percent);
2709 }
2710
2711 /* part->parents could still be 0 so we can't test with totparent */
2712 between = 1;
2713 }
2714
2715 if (use_render_params) {
2716 segments = 1 << part->ren_step;
2717 }
2718 else {
2719 totchild = int(float(totchild) * float(part->disp) / 100.0f);
2720 }
2721
2722 totparent = std::min(totparent, totchild);
2723
2724 if (totchild == 0) {
2725 return false;
2726 }
2727
2728 /* fill context values */
2729 ctx->between = between;
2730 ctx->segments = segments;
2731 if (ELEM(part->kink, PART_KINK_SPIRAL)) {
2732 ctx->extra_segments = max_ii(part->kink_extra_steps, 1);
2733 }
2734 else {
2735 ctx->extra_segments = 0;
2736 }
2737 ctx->totchild = totchild;
2738 ctx->totparent = totparent;
2739 ctx->parent_pass = 0;
2740 ctx->cfra = cfra;
2741 ctx->editupdate = editupdate;
2742
2743 psys_sim_data_init(&ctx->sim);
2744
2745 /* cache all relevant vertex groups if they exist */
2746 ctx->vg_length = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_LENGTH);
2747 ctx->vg_clump = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_CLUMP);
2748 ctx->vg_kink = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_KINK);
2749 ctx->vg_rough1 = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_ROUGH1);
2750 ctx->vg_rough2 = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_ROUGH2);
2751 ctx->vg_roughe = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_ROUGHE);
2752 ctx->vg_twist = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_TWIST);
2753 if (psys->part->flag & PART_CHILD_EFFECT) {
2755 }
2756
2757 /* prepare curvemapping tables */
2758 if ((part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && part->clumpcurve) {
2759 ctx->clumpcurve = BKE_curvemapping_copy(part->clumpcurve);
2761 }
2762 else {
2763 ctx->clumpcurve = nullptr;
2764 }
2765 if ((part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && part->roughcurve) {
2766 ctx->roughcurve = BKE_curvemapping_copy(part->roughcurve);
2768 }
2769 else {
2770 ctx->roughcurve = nullptr;
2771 }
2772 if ((part->child_flag & PART_CHILD_USE_TWIST_CURVE) && part->twistcurve) {
2773 ctx->twistcurve = BKE_curvemapping_copy(part->twistcurve);
2775 }
2776 else {
2777 ctx->twistcurve = nullptr;
2778 }
2779
2780 return true;
2781}
2782
2784{
2785 /* init random number generator */
2786 int seed = 31415926 + sim->psys->seed;
2787
2788 task->rng_path = BLI_rng_new(seed);
2789}
2790
2791/* NOTE: this function must be thread safe, except for branching! */
2793 ChildParticle *cpa,
2794 ParticleCacheKey *child_keys,
2795 int i)
2796{
2797 ParticleThreadContext *ctx = task->ctx;
2798 Object *ob = ctx->sim.ob;
2799 ParticleSystem *psys = ctx->sim.psys;
2800 ParticleSettings *part = psys->part;
2801 ParticleCacheKey **cache = psys->childcache;
2802 PTCacheEdit *edit = psys_orig_edit_get(psys);
2803 ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.depsgraph, psys) && edit ?
2804 edit->pathcache :
2805 psys->pathcache;
2806 ParticleCacheKey *child, *key[4];
2807 ParticleTexture ptex;
2808 float *cpa_fuv = nullptr, *par_rot = nullptr, rot[4];
2809 float orco[3], hairmat[4][4], dvec[3], off1[4][3], off2[4][3];
2810 float eff_length, eff_vec[3], weight[4];
2811 int k, cpa_num;
2812 short cpa_from;
2813
2814 if (!pcache) {
2815 return;
2816 }
2817
2818 if (ctx->between) {
2819 ParticleData *pa = psys->particles + cpa->pa[0];
2820 int w, needupdate;
2821 float foffset, wsum = 0.0f;
2822 float co[3];
2823 float p_min = part->parting_min;
2824 float p_max = part->parting_max;
2825 /* Virtual parents don't work nicely with parting. */
2826 float p_fac = part->parents > 0.0f ? 0.0f : part->parting_fac;
2827
2828 if (ctx->editupdate) {
2829 needupdate = 0;
2830 w = 0;
2831 while (w < 4 && cpa->pa[w] >= 0) {
2832 if (edit->points[cpa->pa[w]].flag & PEP_EDIT_RECALC) {
2833 needupdate = 1;
2834 break;
2835 }
2836 w++;
2837 }
2838
2839 if (!needupdate) {
2840 return;
2841 }
2842
2843 memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
2844 }
2845
2846 /* get parent paths */
2847 for (w = 0; w < 4; w++) {
2848 if (cpa->pa[w] >= 0) {
2849 key[w] = pcache[cpa->pa[w]];
2850 weight[w] = cpa->w[w];
2851 }
2852 else {
2853 key[w] = pcache[0];
2854 weight[w] = 0.0f;
2855 }
2856 }
2857
2858 /* modify weights to create parting */
2859 if (p_fac > 0.0f) {
2860 const ParticleCacheKey *key_0_last = pcache_key_segment_endpoint_safe(key[0]);
2861 for (w = 0; w < 4; w++) {
2862 if (w && (weight[w] > 0.0f)) {
2863 const ParticleCacheKey *key_w_last = pcache_key_segment_endpoint_safe(key[w]);
2864 float d;
2865 if (part->flag & PART_CHILD_LONG_HAIR) {
2866 /* For long hair use tip distance/root distance as parting
2867 * factor instead of root to tip angle. */
2868 float d1 = len_v3v3(key[0]->co, key[w]->co);
2869 float d2 = len_v3v3(key_0_last->co, key_w_last->co);
2870
2871 d = d1 > 0.0f ? d2 / d1 - 1.0f : 10000.0f;
2872 }
2873 else {
2874 float v1[3], v2[3];
2875 sub_v3_v3v3(v1, key_0_last->co, key[0]->co);
2876 sub_v3_v3v3(v2, key_w_last->co, key[w]->co);
2877 normalize_v3(v1);
2879
2880 d = RAD2DEGF(safe_acosf(dot_v3v3(v1, v2)));
2881 }
2882
2883 if (p_max > p_min) {
2884 d = (d - p_min) / (p_max - p_min);
2885 }
2886 else {
2887 d = (d - p_min) <= 0.0f ? 0.0f : 1.0f;
2888 }
2889
2890 CLAMP(d, 0.0f, 1.0f);
2891
2892 if (d > 0.0f) {
2893 weight[w] *= (1.0f - d);
2894 }
2895 }
2896 wsum += weight[w];
2897 }
2898 for (w = 0; w < 4; w++) {
2899 weight[w] /= wsum;
2900 }
2901
2902 interp_v4_v4v4(weight, cpa->w, weight, p_fac);
2903 }
2904
2905 /* get the original coordinates (orco) for texture usage */
2906 cpa_num = cpa->num;
2907
2908 foffset = cpa->foffset;
2909 cpa_fuv = cpa->fuv;
2910 cpa_from = PART_FROM_FACE;
2911
2913 cpa_from,
2914 cpa_num,
2916 cpa->fuv,
2917 foffset,
2918 co,
2919 nullptr,
2920 nullptr,
2921 nullptr,
2922 orco);
2923
2924 mul_m4_v3(ob->object_to_world().ptr(), co);
2925
2926 for (w = 0; w < 4; w++) {
2927 sub_v3_v3v3(off1[w], co, key[w]->co);
2928 }
2929
2930 psys_mat_hair_to_global(ob, ctx->sim.psmd->mesh_final, psys->part->from, pa, hairmat);
2931 }
2932 else {
2933 ParticleData *pa = psys->particles + cpa->parent;
2934 float co[3];
2935 if (ctx->editupdate) {
2936 if (!(edit->points[cpa->parent].flag & PEP_EDIT_RECALC)) {
2937 return;
2938 }
2939
2940 memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
2941 }
2942
2943 /* get the parent path */
2944 key[0] = pcache[cpa->parent];
2945
2946 /* get the original coordinates (orco) for texture usage */
2947 cpa_from = part->from;
2948
2949 /*
2950 * NOTE: Should in theory be the same as:
2951 * cpa_num = psys_particle_dm_face_lookup(
2952 * ctx->sim.psmd->dm_final,
2953 * ctx->sim.psmd->dm_deformed,
2954 * pa->num, pa->fuv,
2955 * nullptr);
2956 */
2957 cpa_num = ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND) ? pa->num : pa->num_dmcache;
2958
2959 /* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
2960 if (cpa_num > ctx->sim.psmd->mesh_final->totface_legacy) {
2961 cpa_num = 0;
2962 }
2963 cpa_fuv = pa->fuv;
2964
2966 cpa_from,
2967 cpa_num,
2969 cpa_fuv,
2970 pa->foffset,
2971 co,
2972 nullptr,
2973 nullptr,
2974 nullptr,
2975 orco);
2976
2977 psys_mat_hair_to_global(ob, ctx->sim.psmd->mesh_final, psys->part->from, pa, hairmat);
2978 }
2979
2980 child_keys->segments = ctx->segments;
2981
2982 /* get different child parameters from textures & vgroups */
2983 get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
2984
2985 if (ptex.exist < psys_frand(psys, i + 24)) {
2986 child_keys->segments = -1;
2987 return;
2988 }
2989
2990 /* create the child path */
2991 for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
2992 if (ctx->between) {
2993 int w = 0;
2994
2995 zero_v3(child->co);
2996 zero_v3(child->vel);
2997 unit_qt(child->rot);
2998
2999 for (w = 0; w < 4; w++) {
3000 copy_v3_v3(off2[w], off1[w]);
3001
3002 if (part->flag & PART_CHILD_LONG_HAIR) {
3003 /* Use parent rotation (in addition to emission location) to determine child offset. */
3004 if (k) {
3005 mul_qt_v3((key[w] + k)->rot, off2[w]);
3006 }
3007
3008 /* Fade the effect of rotation for even lengths in the end */
3009 project_v3_v3v3(dvec, off2[w], (key[w] + k)->vel);
3010 madd_v3_v3fl(off2[w], dvec, -float(k) / float(ctx->segments));
3011 }
3012
3013 add_v3_v3(off2[w], (key[w] + k)->co);
3014 }
3015
3016 /* child position is the weighted sum of parent positions */
3017 interp_v3_v3v3v3v3(child->co, off2[0], off2[1], off2[2], off2[3], weight);
3018 interp_v3_v3v3v3v3(child->vel,
3019 (key[0] + k)->vel,
3020 (key[1] + k)->vel,
3021 (key[2] + k)->vel,
3022 (key[3] + k)->vel,
3023 weight);
3024
3025 copy_qt_qt(child->rot, (key[0] + k)->rot);
3026 }
3027 else {
3028 if (k) {
3029 mul_qt_qtqt(rot, (key[0] + k)->rot, key[0]->rot);
3030 par_rot = rot;
3031 }
3032 else {
3033 par_rot = key[0]->rot;
3034 }
3035 /* offset the child from the parent position */
3036 offset_child(cpa,
3037 (ParticleKey *)(key[0] + k),
3038 par_rot,
3039 (ParticleKey *)child,
3040 part->childflat,
3041 part->childrad);
3042 }
3043
3044 child->time = float(k) / float(ctx->segments);
3045 }
3046
3047 /* apply effectors */
3048 if (part->flag & PART_CHILD_EFFECT) {
3049 for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
3050 if (k) {
3051 do_path_effectors(&ctx->sim,
3052 cpa->pa[0],
3053 child,
3054 k,
3055 ctx->segments,
3056 child_keys->co,
3057 ptex.effector,
3058 0.0f,
3059 ctx->cfra,
3060 &eff_length,
3061 eff_vec);
3062 }
3063 else {
3064 sub_v3_v3v3(eff_vec, (child + 1)->co, child->co);
3065 eff_length = len_v3(eff_vec);
3066 }
3067 }
3068 }
3069
3070 {
3071 ParticleData *pa = nullptr;
3072 ParticleCacheKey *par = nullptr;
3073 float par_co[3];
3074 float par_orco[3];
3075
3076 if (ctx->totparent) {
3077 if (i >= ctx->totparent) {
3078 pa = &psys->particles[cpa->parent];
3079 /* this is now threadsafe, virtual parents are calculated before rest of children */
3080 BLI_assert(cpa->parent < psys->totchildcache);
3081 par = cache[cpa->parent];
3082 }
3083 }
3084 else if (cpa->parent >= 0) {
3085 pa = &psys->particles[cpa->parent];
3086 par = pcache[cpa->parent];
3087
3088 /* If particle is non-existing, try to pick a viable parent from particles
3089 * used for interpolation. */
3090 for (k = 0; k < 4 && pa && (pa->flag & PARS_UNEXIST); k++) {
3091 if (cpa->pa[k] >= 0) {
3092 pa = &psys->particles[cpa->pa[k]];
3093 par = pcache[cpa->pa[k]];
3094 }
3095 }
3096
3097 if (pa->flag & PARS_UNEXIST) {
3098 pa = nullptr;
3099 }
3100 }
3101
3102 if (pa) {
3103 ListBase modifiers;
3104 BLI_listbase_clear(&modifiers);
3105
3107 part->from,
3108 pa->num,
3109 pa->num_dmcache,
3110 pa->fuv,
3111 pa->foffset,
3112 par_co,
3113 nullptr,
3114 nullptr,
3115 nullptr,
3116 par_orco);
3117
3119 ctx, &modifiers, cpa, &ptex, orco, hairmat, child_keys, par, par_orco);
3120 }
3121 else {
3122 zero_v3(par_orco);
3123 }
3124 }
3125
3126 /* Hide virtual parents */
3127 if (i < ctx->totparent) {
3128 child_keys->segments = -1;
3129 }
3130}
3131
3132static void exec_child_path_cache(TaskPool *__restrict /*pool*/, void *taskdata)
3133{
3134 ParticleTask *task = static_cast<ParticleTask *>(taskdata);
3135 ParticleThreadContext *ctx = task->ctx;
3136 ParticleSystem *psys = ctx->sim.psys;
3137 ParticleCacheKey **cache = psys->childcache;
3138 ChildParticle *cpa;
3139 int i;
3140
3141 cpa = psys->child + task->begin;
3142 for (i = task->begin; i < task->end; i++, cpa++) {
3143 BLI_assert(i < psys->totchildcache);
3144 psys_thread_create_path(task, cpa, cache[i], i);
3145 }
3146}
3147
3149 float cfra,
3150 const bool editupdate,
3151 const bool use_render_params)
3152{
3155 ParticleTask *tasks_parent, *tasks_child;
3156 int numtasks_parent, numtasks_child;
3157 int i, totchild, totparent;
3158
3159 if (sim->psys->flag & PSYS_GLOBAL_HAIR) {
3160 return;
3161 }
3162
3163 /* create a task pool for child path tasks */
3164 if (!psys_thread_context_init_path(&ctx, sim, sim->scene, cfra, editupdate, use_render_params)) {
3165 return;
3166 }
3167
3169 totchild = ctx.totchild;
3170 totparent = ctx.totparent;
3171
3172 if (editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) {
3173 /* just overwrite the existing cache */
3174 }
3175 else {
3176 /* clear out old and create new empty path cache */
3178
3180 &sim->psys->childcachebufs, totchild, ctx.segments + ctx.extra_segments + 1);
3181 sim->psys->totchildcache = totchild;
3182 }
3183
3184 /* cache parent paths */
3185 ctx.parent_pass = 1;
3186 psys_tasks_create(&ctx, 0, totparent, &tasks_parent, &numtasks_parent);
3187 for (i = 0; i < numtasks_parent; i++) {
3188 ParticleTask *task = &tasks_parent[i];
3189
3190 psys_task_init_path(task, sim);
3191 BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, nullptr);
3192 }
3194
3195 /* cache child paths */
3196 ctx.parent_pass = 0;
3197 psys_tasks_create(&ctx, totparent, totchild, &tasks_child, &numtasks_child);
3198 for (i = 0; i < numtasks_child; i++) {
3199 ParticleTask *task = &tasks_child[i];
3200
3201 psys_task_init_path(task, sim);
3202 BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, nullptr);
3203 }
3205
3207
3208 psys_tasks_free(tasks_parent, numtasks_parent);
3209 psys_tasks_free(tasks_child, numtasks_child);
3210
3212}
3213
3214/* figure out incremental rotations along path starting from unit quat */
3216 ParticleCacheKey *key1,
3217 ParticleCacheKey *key2,
3218 float *prev_tangent,
3219 int i)
3220{
3221 float cosangle, angle, tangent[3], normal[3], q[4];
3222
3223 switch (i) {
3224 case 0:
3225 /* start from second key */
3226 break;
3227 case 1:
3228 /* calculate initial tangent for incremental rotations */
3229 sub_v3_v3v3(prev_tangent, key0->co, key1->co);
3230 normalize_v3(prev_tangent);
3231 unit_qt(key1->rot);
3232 break;
3233 default:
3234 sub_v3_v3v3(tangent, key0->co, key1->co);
3235 normalize_v3(tangent);
3236
3237 cosangle = dot_v3v3(tangent, prev_tangent);
3238
3239 /* note we do the comparison on cosangle instead of
3240 * angle, since floating point accuracy makes it give
3241 * different results across platforms */
3242 if (cosangle > 0.999999f) {
3243 copy_v4_v4(key1->rot, key2->rot);
3244 }
3245 else {
3246 angle = safe_acosf(cosangle);
3247 cross_v3_v3v3(normal, prev_tangent, tangent);
3248 axis_angle_to_quat(q, normal, angle);
3249 mul_qt_qtqt(key1->rot, q, key2->rot);
3250 }
3251
3252 copy_v3_v3(prev_tangent, tangent);
3253 }
3254}
3255
3256void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_render_params)
3257{
3260 ParticleSystem *psys = sim->psys;
3261 ParticleSettings *part = psys->part;
3262 ParticleCacheKey *ca, **cache;
3263
3264 Mesh *hair_mesh = (psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) ?
3265 psys->hair_out_mesh :
3266 nullptr;
3267
3269
3270 Material *ma;
3272 ParticleTexture ptex;
3273
3274 PARTICLE_P;
3275
3276 float birthtime = 0.0, dietime = 0.0;
3277 float t, time = 0.0, dfra = 1.0;
3278 float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
3279 float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
3280 float rotmat[3][3];
3281 int k;
3282 int segments = int(pow(2.0, double((use_render_params) ? part->ren_step : part->draw_step)));
3283 int totpart = psys->totpart;
3284 float length, vec[3];
3285 float *vg_effector = nullptr;
3286 float *vg_length = nullptr, pa_length = 1.0f;
3287 int keyed, baked;
3288
3289 /* we don't have anything valid to create paths from so let's quit here */
3290 if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0) {
3291 return;
3292 }
3293
3294 if (psys_in_edit_mode(sim->depsgraph, psys)) {
3295 if ((psys->edit == nullptr || pset->flag & PE_DRAW_PART) == 0) {
3296 return;
3297 }
3298 }
3299
3300 keyed = psys->flag & PSYS_KEYED;
3301 baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR;
3302
3303 /* clear out old and create new empty path cache */
3304 psys_free_path_cache(psys, psys->edit);
3306 &psys->pathcachebufs, totpart, segments + 1);
3307
3308 psys_sim_data_init(sim);
3309 ma = BKE_object_material_get(sim->ob, psys->part->omat);
3310 if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT)) {
3311 copy_v3_v3(col, &ma->r);
3312 }
3313
3314 if ((psys->flag & PSYS_GLOBAL_HAIR) == 0) {
3315 if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
3316 vg_effector = psys_cache_vgroup(psmd->mesh_final, psys, PSYS_VG_EFFECTOR);
3317 }
3318
3319 if (!psys->totchild) {
3320 vg_length = psys_cache_vgroup(psmd->mesh_final, psys, PSYS_VG_LENGTH);
3321 }
3322 }
3323
3324 /* ensure we have tessfaces to be used for mapping */
3325 if (part->from != PART_FROM_VERT) {
3326 BKE_mesh_tessface_ensure(psmd->mesh_final);
3327 }
3328
3329 /*---first main loop: create all actual particles' paths---*/
3331 {
3332 if (!psys->totchild) {
3333 psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.0f);
3334 pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
3335 if (vg_length) {
3336 pa_length *= psys_particle_value_from_verts(psmd->mesh_final, part->from, pa, vg_length);
3337 }
3338 }
3339
3340 pind.keyed = keyed;
3341 pind.cache = baked ? psys->pointcache : nullptr;
3342 pind.epoint = nullptr;
3343 pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
3344 pind.mesh = hair_mesh;
3345
3346 memset(cache[p], 0, sizeof(*cache[p]) * (segments + 1));
3347
3348 cache[p]->segments = segments;
3349
3350 /*--get the first data points--*/
3351 init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
3352
3353 /* 'hairmat' is needed for non-hair particle too so we get proper rotations. */
3354 psys_mat_hair_to_global(sim->ob, psmd->mesh_final, psys->part->from, pa, hairmat);
3355 copy_v3_v3(rotmat[0], hairmat[2]);
3356 copy_v3_v3(rotmat[1], hairmat[1]);
3357 copy_v3_v3(rotmat[2], hairmat[0]);
3358
3359 if (part->draw & PART_ABS_PATH_TIME) {
3360 birthtime = std::max(pind.birthtime, part->path_start);
3361 dietime = std::min(pind.dietime, part->path_end);
3362 }
3363 else {
3364 float tb = pind.birthtime;
3365 birthtime = tb + part->path_start * (pind.dietime - tb);
3366 dietime = tb + part->path_end * (pind.dietime - tb);
3367 }
3368
3369 if (birthtime >= dietime) {
3370 cache[p]->segments = -1;
3371 continue;
3372 }
3373
3374 dietime = birthtime + pa_length * (dietime - birthtime);
3375
3376 /*--interpolate actual path from data points--*/
3377 for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
3378 time = float(k) / float(segments);
3379 t = birthtime + time * (dietime - birthtime);
3380 result.time = -t;
3381 do_particle_interpolation(psys, p, pa, t, &pind, &result);
3382 copy_v3_v3(ca->co, result.co);
3383
3384 /* dynamic hair is in object space */
3385 /* keyed and baked are already in global space */
3386 if (hair_mesh) {
3387 mul_m4_v3(sim->ob->object_to_world().ptr(), ca->co);
3388 }
3389 else if (!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) {
3390 mul_m4_v3(hairmat, ca->co);
3391 }
3392
3393 copy_v3_v3(ca->col, col);
3394 }
3395
3396 if (part->type == PART_HAIR) {
3397 HairKey *hkey;
3398
3399 for (k = 0, hkey = pa->hair; k < pa->totkey; k++, hkey++) {
3400 mul_v3_m4v3(hkey->world_co, hairmat, hkey->co);
3401 }
3402 }
3403
3404 /*--modify paths and calculate rotation & velocity--*/
3405
3406 if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
3407 /* apply effectors */
3408 if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
3409 float effector = 1.0f;
3410 if (vg_effector) {
3412 psmd->mesh_final, psys->part->from, pa, vg_effector);
3413 }
3414
3415 sub_v3_v3v3(vec, (cache[p] + 1)->co, cache[p]->co);
3416 length = len_v3(vec);
3417
3418 for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++) {
3420 sim, p, ca, k, segments, cache[p]->co, effector, dfra, cfra, &length, vec);
3421 }
3422 }
3423
3424 /* apply guide curves to path data */
3425 if (sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT) == 0) {
3426 for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
3427 /* ca is safe to cast, since only co and vel are used */
3428 do_guides(sim->depsgraph,
3429 sim->psys->part,
3430 sim->psys->effectors,
3431 (ParticleKey *)ca,
3432 p,
3433 float(k) / float(segments));
3434 }
3435 }
3436
3437 /* Lattices have to be calculated separately to avoid mix-ups between effector calculations.
3438 */
3439 if (psys->lattice_deform_data) {
3440 for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
3442 psys->lattice_deform_data, ca->co, psys->lattice_strength);
3443 }
3444 }
3445 }
3446
3447 /* finally do rotation & velocity */
3448 for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++) {
3449 cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
3450
3451 if (k == segments) {
3452 copy_qt_qt(ca->rot, (ca - 1)->rot);
3453 }
3454
3455 /* set velocity */
3456 sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
3457
3458 if (k == 1) {
3459 copy_v3_v3((ca - 1)->vel, ca->vel);
3460 }
3461
3462 ca->time = float(k) / float(segments);
3463 }
3464 /* First rotation is based on emitting face orientation.
3465 * This is way better than having flipping rotations resulting
3466 * from using a global axis as a rotation pole (vec_to_quat()).
3467 * It's not an ideal solution though since it disregards the
3468 * initial tangent, but taking that in to account will allow
3469 * the possibility of flipping again. -jahka
3470 */
3471 mat3_to_quat_legacy(cache[p]->rot, rotmat);
3472 }
3473
3474 psys->totcached = totpart;
3475
3476 psys_sim_data_free(sim);
3477
3478 if (vg_effector) {
3479 MEM_freeN(vg_effector);
3480 }
3481
3482 if (vg_length) {
3483 MEM_freeN(vg_length);
3484 }
3485}
3486
3495
3496static void psys_cache_edit_paths_iter(void *__restrict iter_data_v,
3497 const int iter,
3498 const TaskParallelTLS *__restrict /*tls*/)
3499{
3500 CacheEditrPathsIterData *iter_data = (CacheEditrPathsIterData *)iter_data_v;
3501 PTCacheEdit *edit = iter_data->edit;
3502 PTCacheEditPoint *point = &edit->points[iter];
3503 if (edit->totcached && !(point->flag & PEP_EDIT_RECALC)) {
3504 return;
3505 }
3506 if (point->totkey == 0) {
3507 return;
3508 }
3509 Object *ob = iter_data->object;
3510 ParticleSystem *psys = edit->psys;
3511 ParticleCacheKey **cache = edit->pathcache;
3512 ParticleSystemModifierData *psmd = iter_data->psmd;
3513 ParticleData *pa = iter_data->pa ? iter_data->pa + iter : nullptr;
3514 PTCacheEditKey *ekey = point->keys;
3515 const int segments = iter_data->segments;
3516 const bool use_weight = iter_data->use_weight;
3517
3518 float birthtime = 0.0f, dietime = 0.0f;
3519 float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f};
3520
3522 pind.keyed = 0;
3523 pind.cache = nullptr;
3524 pind.epoint = point;
3525 pind.bspline = psys ? (psys->part->flag & PART_HAIR_BSPLINE) : 0;
3526 pind.mesh = nullptr;
3527
3528 /* should init_particle_interpolation set this ? */
3529 if (use_weight) {
3530 pind.hkey[0] = nullptr;
3531 /* pa != nullptr since the weight brush is only available for hair */
3532 pind.hkey[0] = pa->hair;
3533 pind.hkey[1] = pa->hair + 1;
3534 }
3535
3536 memset(cache[iter], 0, sizeof(*cache[iter]) * (segments + 1));
3537
3538 cache[iter]->segments = segments;
3539
3540 /*--get the first data points--*/
3541 init_particle_interpolation(ob, psys, pa, &pind);
3542
3543 if (psys) {
3544 psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
3545 copy_v3_v3(rotmat[0], hairmat[2]);
3546 copy_v3_v3(rotmat[1], hairmat[1]);
3547 copy_v3_v3(rotmat[2], hairmat[0]);
3548 }
3549
3550 birthtime = pind.birthtime;
3551 dietime = pind.dietime;
3552
3553 if (birthtime >= dietime) {
3554 cache[iter]->segments = -1;
3555 return;
3556 }
3557
3558 /*--interpolate actual path from data points--*/
3559 ParticleCacheKey *ca;
3560 int k;
3561 float t, time = 0.0f, keytime = 0.0f;
3562 for (k = 0, ca = cache[iter]; k <= segments; k++, ca++) {
3563 time = float(k) / float(segments);
3564 t = birthtime + time * (dietime - birthtime);
3566 result.time = -t;
3567 do_particle_interpolation(psys, iter, pa, t, &pind, &result);
3568 copy_v3_v3(ca->co, result.co);
3569
3570 /* non-hair points are already in global space */
3571 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
3572 mul_m4_v3(hairmat, ca->co);
3573
3574 if (k) {
3575 cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
3576
3577 if (k == segments) {
3578 copy_qt_qt(ca->rot, (ca - 1)->rot);
3579 }
3580
3581 /* set velocity */
3582 sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
3583
3584 if (k == 1) {
3585 copy_v3_v3((ca - 1)->vel, ca->vel);
3586 }
3587 }
3588 }
3589 else {
3590 ca->vel[0] = ca->vel[1] = 0.0f;
3591 ca->vel[2] = 1.0f;
3592 }
3593
3594 /* selection coloring in edit mode */
3595 if (use_weight) {
3596 if (k == 0) {
3598 }
3599 else {
3600 /* WARNING: copied from 'do_particle_interpolation' (without 'vertex' array stepping) */
3601 float real_t;
3602 if (result.time < 0.0f) {
3603 real_t = -result.time;
3604 }
3605 else {
3606 real_t = pind.hkey[0]->time +
3607 t * (pind.hkey[0][pa->totkey - 1].time - pind.hkey[0]->time);
3608 }
3609
3610 while (pind.hkey[1]->time < real_t) {
3611 pind.hkey[1]++;
3612 }
3613 pind.hkey[0] = pind.hkey[1] - 1;
3614 /* end copy */
3615
3616 float w1[3], w2[3];
3617 keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
3618
3621
3622 interp_v3_v3v3(ca->col, w1, w2, keytime);
3623 }
3624 }
3625 else {
3626 /* HACK(fclem): Instead of setting the color we pass the select state in the red channel.
3627 * This is then picked up in DRW and the gpu shader will do the color interpolation. */
3628 if ((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT) {
3629 if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
3630 ca->col[0] = 1.0f;
3631 }
3632 else {
3633 keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
3634 ca->col[0] = 1.0f - keytime;
3635 }
3636 }
3637 else {
3638 if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
3639 keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
3640 ca->col[0] = keytime;
3641 }
3642 else {
3643 ca->col[0] = 0.0f;
3644 }
3645 }
3646 }
3647
3648 ca->time = t;
3649 }
3650 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
3651 /* First rotation is based on emitting face orientation.
3652 * This is way better than having flipping rotations resulting
3653 * from using a global axis as a rotation pole (vec_to_quat()).
3654 * It's not an ideal solution though since it disregards the
3655 * initial tangent, but taking that in to account will allow
3656 * the possibility of flipping again. -jahka
3657 */
3658 mat3_to_quat_legacy(cache[iter]->rot, rotmat);
3659 }
3660}
3661
3663 Scene *scene,
3664 Object *ob,
3665 PTCacheEdit *edit,
3666 float cfra,
3667 const bool use_render_params)
3668{
3669 ParticleCacheKey **cache = edit->pathcache;
3670 ParticleEditSettings *pset = &scene->toolsettings->particle;
3671
3672 ParticleSystem *psys = edit->psys;
3673
3674 ParticleData *pa = psys ? psys->particles : nullptr;
3675
3676 int segments = 1 << pset->draw_step;
3677 int totpart = edit->totpoint, recalc_set = 0;
3678
3679 if (edit->psmd_eval == nullptr) {
3680 return;
3681 }
3682
3683 segments = std::max(segments, 4);
3684
3685 if (!cache || edit->totpoint != edit->totcached) {
3686 /* Clear out old and create new empty path cache. */
3687 psys_free_path_cache(edit->psys, edit);
3689 &edit->pathcachebufs, totpart, segments + 1);
3690 /* Set flag for update (child particles check this too). */
3691 int i;
3693 for (i = 0, point = edit->points; i < totpart; i++, point++) {
3694 point->flag |= PEP_EDIT_RECALC;
3695 }
3696 recalc_set = 1;
3697 }
3698
3699 const bool use_weight = (pset->brushtype == PE_BRUSH_WEIGHT) && (psys != nullptr) &&
3700 (psys->particles != nullptr);
3701
3702 CacheEditrPathsIterData iter_data;
3703 iter_data.object = ob;
3704 iter_data.edit = edit;
3705 iter_data.psmd = edit->psmd_eval;
3706 iter_data.pa = pa;
3707 iter_data.segments = segments;
3708 iter_data.use_weight = use_weight;
3709
3710 TaskParallelSettings settings;
3712 BLI_task_parallel_range(0, edit->totpoint, &iter_data, psys_cache_edit_paths_iter, &settings);
3713
3714 edit->totcached = totpart;
3715
3716 if (psys) {
3717 ParticleSimulationData sim = {nullptr};
3718 sim.depsgraph = depsgraph;
3719 sim.scene = scene;
3720 sim.ob = ob;
3721 sim.psys = psys;
3722 sim.psmd = edit->psmd_eval;
3723
3724 psys_cache_child_paths(&sim, cfra, true, use_render_params);
3725 }
3726
3727 /* clear recalc flag if set here */
3728 if (recalc_set) {
3730 int i;
3731 for (i = 0, point = edit->points; i < totpart; i++, point++) {
3732 point->flag &= ~PEP_EDIT_RECALC;
3733 }
3734 }
3735}
3736
3737/************************************************/
3738/* Particle Key handling */
3739/************************************************/
3740
3742{
3743 if (time) {
3744 memcpy(to, from, sizeof(ParticleKey));
3745 }
3746 else {
3747 float to_time = to->time;
3748 memcpy(to, from, sizeof(ParticleKey));
3749 to->time = to_time;
3750 }
3751}
3752void psys_get_from_key(ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time)
3753{
3754 if (loc) {
3755 copy_v3_v3(loc, key->co);
3756 }
3757 if (vel) {
3758 copy_v3_v3(vel, key->vel);
3759 }
3760 if (rot) {
3761 copy_qt_qt(rot, key->rot);
3762 }
3763 if (time) {
3764 *time = key->time;
3765 }
3766}
3767
3768static void triatomat(float *v1, float *v2, float *v3, const float (*uv)[2], float mat[4][4])
3769{
3770 float det, w1, w2, d1[2], d2[2];
3771
3772 memset(mat, 0, sizeof(float[4][4]));
3773 mat[3][3] = 1.0f;
3774
3775 /* first axis is the normal */
3776 normal_tri_v3(mat[2], v1, v2, v3);
3777
3778 /* second axis along (1, 0) in uv space */
3779 if (uv) {
3780 d1[0] = uv[1][0] - uv[0][0];
3781 d1[1] = uv[1][1] - uv[0][1];
3782 d2[0] = uv[2][0] - uv[0][0];
3783 d2[1] = uv[2][1] - uv[0][1];
3784
3785 det = d2[0] * d1[1] - d2[1] * d1[0];
3786
3787 if (det != 0.0f) {
3788 det = 1.0f / det;
3789 w1 = -d2[1] * det;
3790 w2 = d1[1] * det;
3791
3792 mat[1][0] = w1 * (v2[0] - v1[0]) + w2 * (v3[0] - v1[0]);
3793 mat[1][1] = w1 * (v2[1] - v1[1]) + w2 * (v3[1] - v1[1]);
3794 mat[1][2] = w1 * (v2[2] - v1[2]) + w2 * (v3[2] - v1[2]);
3795 normalize_v3(mat[1]);
3796 }
3797 else {
3798 mat[1][0] = mat[1][1] = mat[1][2] = 0.0f;
3799 }
3800 }
3801 else {
3802 sub_v3_v3v3(mat[1], v2, v1);
3803 normalize_v3(mat[1]);
3804 }
3805
3806 /* third as a cross product */
3807 cross_v3_v3v3(mat[0], mat[1], mat[2]);
3808}
3809
3810static void psys_face_mat(Object *ob, Mesh *mesh, ParticleData *pa, float mat[4][4], int orco)
3811{
3812 float v[3][3];
3813 MFace *mface;
3814 const float(*orcodata)[3];
3815
3817 if (i == -1 || i >= mesh->totface_legacy) {
3818 unit_m4(mat);
3819 return;
3820 }
3821
3822 MFace *mfaces = static_cast<MFace *>(
3823 CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy));
3824 mface = &mfaces[i];
3825 const OrigSpaceFace *osface = static_cast<const OrigSpaceFace *>(
3826 CustomData_get_for_write(&mesh->fdata_legacy, i, CD_ORIGSPACE, mesh->totface_legacy));
3827
3828 if (orco &&
3829 (orcodata = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh->vert_data, CD_ORCO))))
3830 {
3831 copy_v3_v3(v[0], orcodata[mface->v1]);
3832 copy_v3_v3(v[1], orcodata[mface->v2]);
3833 copy_v3_v3(v[2], orcodata[mface->v3]);
3834
3835 /* ugly hack to use non-transformed orcos, since only those
3836 * give symmetric results for mirroring in particle mode */
3837 if (CustomData_get_layer(&mesh->vert_data, CD_ORIGINDEX)) {
3838 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), v, 3, true);
3839 }
3840 }
3841 else {
3842 const blender::Span<blender::float3> vert_positions = mesh->vert_positions();
3843 copy_v3_v3(v[0], vert_positions[mface->v1]);
3844 copy_v3_v3(v[1], vert_positions[mface->v2]);
3845 copy_v3_v3(v[2], vert_positions[mface->v3]);
3846 }
3847
3848 triatomat(v[0], v[1], v[2], (osface) ? osface->uv : nullptr, mat);
3849}
3850
3852 Object * /*ob*/, Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
3853{
3854 float vec[3];
3855
3856 /* can happen when called from a different object's modifier */
3857 if (!mesh) {
3858 unit_m4(hairmat);
3859 return;
3860 }
3861
3862 psys_face_mat(nullptr, mesh, pa, hairmat, 0);
3864 from,
3865 pa->num,
3866 pa->num_dmcache,
3867 pa->fuv,
3868 pa->foffset,
3869 vec,
3870 nullptr,
3871 nullptr,
3872 nullptr,
3873 nullptr);
3874 copy_v3_v3(hairmat[3], vec);
3875}
3876
3878 Object *ob, Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
3879{
3880 float vec[3], orco[3];
3881
3882 psys_face_mat(ob, mesh, pa, hairmat, 1);
3884 from,
3885 pa->num,
3886 pa->num_dmcache,
3887 pa->fuv,
3888 pa->foffset,
3889 vec,
3890 nullptr,
3891 nullptr,
3892 nullptr,
3893 orco);
3894
3895 copy_v3_v3(hairmat[3], orco);
3896}
3897
3898void psys_vec_rot_to_face(Mesh *mesh, ParticleData *pa, float vec[3])
3899{
3900 float mat[4][4];
3901
3902 psys_face_mat(nullptr, mesh, pa, mat, 0);
3903 transpose_m4(mat); /* cheap inverse for rotation matrix */
3904 mul_mat3_m4_v3(mat, vec);
3905}
3906
3908 Object *ob, Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
3909{
3910 float facemat[4][4];
3911
3912 psys_mat_hair_to_object(ob, mesh, from, pa, facemat);
3913
3914 mul_m4_m4m4(hairmat, ob->object_to_world().ptr(), facemat);
3915}
3916
3917/************************************************/
3918/* ParticleSettings handling */
3919/************************************************/
3920
3922 Main *bmain, const Scene *scene, Object *ob, const char *name, const ParticleSystem *psys_orig)
3923{
3924 ParticleSystem *psys;
3925 ModifierData *md;
3927
3928 if (!ob || ob->type != OB_MESH) {
3929 return nullptr;
3930 }
3931
3932 if (name == nullptr) {
3933 name = (psys_orig != nullptr) ? psys_orig->name : DATA_("ParticleSystem");
3934 }
3935
3936 psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
3937 for (; psys; psys = psys->next) {
3938 psys->flag &= ~PSYS_CURRENT;
3939 }
3940
3941 psys = static_cast<ParticleSystem *>(MEM_callocN(sizeof(ParticleSystem), "particle_system"));
3942 psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
3943 BLI_addtail(&ob->particlesystem, psys);
3944 psys_unique_name(ob, psys, name);
3945
3946 if (psys_orig != nullptr) {
3947 psys->part = psys_orig->part;
3948 id_us_plus(&psys->part->id);
3949 }
3950 else {
3951 psys->part = BKE_particlesettings_add(bmain, DATA_("ParticleSettings"));
3952 }
3954 STRNCPY(md->name, psys->name);
3956
3957 psmd = (ParticleSystemModifierData *)md;
3958 psmd->psys = psys;
3959 BLI_addtail(&ob->modifiers, md);
3962
3963 psys->totpart = 0;
3964 psys->flag = PSYS_CURRENT;
3965 if (scene != nullptr) {
3966 psys->cfra = BKE_scene_frame_to_ctime(scene, scene->r.cfra + 1);
3967 }
3968
3971
3972 return md;
3973}
3974
3976 const Scene *scene,
3977 Object *ob,
3978 const char *name)
3979{
3980 return object_add_or_copy_particle_system(bmain, scene, ob, name, nullptr);
3981}
3982
3984 const Scene *scene,
3985 Object *ob,
3986 const ParticleSystem *psys_orig)
3987{
3988 return object_add_or_copy_particle_system(bmain, scene, ob, nullptr, psys_orig);
3989}
3990
3992 Scene * /*scene*/,
3993 Object *ob,
3994 ParticleSystem *psys)
3995{
3996 if (!ob || !psys) {
3997 return;
3998 }
3999
4001 ModifierData *md;
4002
4003 /* Clear particle system in fluid modifier. */
4006
4007 /* Clear particle system pointer in flow settings. */
4008 if ((fmd->type == MOD_FLUID_TYPE_FLOW) && fmd->flow && fmd->flow->psys) {
4009 if (fmd->flow->psys == psys) {
4010 fmd->flow->psys = nullptr;
4011 }
4012 }
4013 /* Clear particle flag in domain settings when removing particle system manually. */
4014 if (fmd->type == MOD_FLUID_TYPE_DOMAIN) {
4015 if (psys->part->type == PART_FLUID_FLIP) {
4016 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP;
4017 }
4018 if (ELEM(psys->part->type,
4023 {
4024 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_SPRAY;
4025 }
4026 if (ELEM(psys->part->type,
4031 {
4032 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FOAM;
4033 }
4034 if (ELEM(psys->part->type,
4039 {
4040 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_BUBBLE;
4041 }
4042 if (psys->part->type == PART_FLUID_TRACER) {
4043 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_TRACER;
4044 }
4045
4046 /* Disable combined export if combined particle system was deleted. */
4047 if (ELEM(psys->part->type,
4052 {
4054 }
4055 }
4056 }
4057
4060 if (pmd->brush && pmd->brush->psys) {
4061 if (pmd->brush->psys == psys) {
4062 pmd->brush->psys = nullptr;
4063 }
4064 }
4065 }
4066
4067 /* Clear modifier, skip empty ones. */
4068 psmd = psys_get_modifier(ob, psys);
4069 if (psmd) {
4072 }
4073
4074 /* Clear particle system. */
4075 BLI_remlink(&ob->particlesystem, psys);
4076 if (psys->part) {
4077 id_us_min(&psys->part->id);
4078 }
4079 psys_free(ob, psys);
4080
4081 if (ob->particlesystem.first) {
4083 }
4084 else {
4085 ob->mode &= ~OB_MODE_PARTICLE_EDIT;
4086 }
4087
4090
4091 /* Flush object mode. */
4093}
4094
4096{
4097 ParticleSettings *part;
4098
4099 part = static_cast<ParticleSettings *>(BKE_id_new(bmain, ID_PA, name));
4100
4101 return part;
4102}
4103
4105{
4106 CurveMapping *cumap = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
4107
4108 cumap->cm[0].curve[0].x = 0.0f;
4109 cumap->cm[0].curve[0].y = 1.0f;
4110 cumap->cm[0].curve[1].x = 1.0f;
4111 cumap->cm[0].curve[1].y = 1.0f;
4112
4113 BKE_curvemapping_init(cumap);
4114
4115 part->clumpcurve = cumap;
4116}
4117
4119{
4120 CurveMapping *cumap = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
4121
4122 cumap->cm[0].curve[0].x = 0.0f;
4123 cumap->cm[0].curve[0].y = 1.0f;
4124 cumap->cm[0].curve[1].x = 1.0f;
4125 cumap->cm[0].curve[1].y = 1.0f;
4126
4127 BKE_curvemapping_init(cumap);
4128
4129 part->roughcurve = cumap;
4130}
4131
4133{
4134 CurveMapping *cumap = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
4135
4136 cumap->cm[0].curve[0].x = 0.0f;
4137 cumap->cm[0].curve[0].y = 1.0f;
4138 cumap->cm[0].curve[1].x = 1.0f;
4139 cumap->cm[0].curve[1].y = 1.0f;
4140
4141 BKE_curvemapping_init(cumap);
4142
4143 part->twistcurve = cumap;
4144}
4145
4146/************************************************/
4147/* Textures */
4148/************************************************/
4149
4150static int get_particle_uv(Mesh *mesh,
4151 ParticleData *pa,
4152 int index,
4153 const float fuv[4],
4154 char *name,
4155 float *texco,
4156 bool from_vert)
4157{
4159 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
4160 MFace *mf;
4161 const MTFace *tf;
4162 int i;
4163
4164 tf = static_cast<const MTFace *>(
4165 CustomData_get_layer_named(&mesh->fdata_legacy, CD_MTFACE, name));
4166 if (tf == nullptr) {
4167 tf = static_cast<const MTFace *>(CustomData_get_layer(&mesh->fdata_legacy, CD_MTFACE));
4168 }
4169 if (tf == nullptr) {
4170 return 0;
4171 }
4172
4173 if (pa) {
4175 if ((!from_vert && i >= mesh->totface_legacy) || (from_vert && i >= mesh->verts_num)) {
4176 i = -1;
4177 }
4178 }
4179 else {
4180 i = index;
4181 }
4182
4183 if (i == -1) {
4184 texco[0] = 0.0f;
4185 texco[1] = 0.0f;
4186 texco[2] = 0.0f;
4187 }
4188 else {
4189 if (from_vert) {
4190 mf = mfaces;
4191
4192 /* This finds the first face to contain the emitting vertex,
4193 * this is not ideal, but is mostly fine as UV seams generally
4194 * map to equal-colored parts of a texture */
4195 for (int j = 0; j < mesh->totface_legacy; j++, mf++) {
4196 if (ELEM(i, mf->v1, mf->v2, mf->v3, mf->v4)) {
4197 i = j;
4198 break;
4199 }
4200 }
4201 }
4202 else {
4203 mf = &mfaces[i];
4204 }
4205
4206 psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco);
4207
4208 texco[0] = texco[0] * 2.0f - 1.0f;
4209 texco[1] = texco[1] * 2.0f - 1.0f;
4210 texco[2] = 0.0f;
4211 }
4212
4213 return 1;
4214}
4215
4216#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \
4217 if ((event & mtex->mapto) & type) { \
4218 pvalue = texture_value_blend(def, pvalue, value, texfac, blend); \
4219 } \
4220 (void)0
4221
4222#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \
4223 if (event & type) { \
4224 CLAMP(pvalue, 0.0f, 1.0f); \
4225 } \
4226 (void)0
4227
4228#define CLAMP_WARP_PARTICLE_TEXTURE_POS(type, pvalue) \
4229 if (event & type) { \
4230 if (pvalue < 0.0f) { \
4231 pvalue = 1.0f + pvalue; \
4232 } \
4233 CLAMP(pvalue, 0.0f, 1.0f); \
4234 } \
4235 (void)0
4236
4237#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \
4238 if (event & type) { \
4239 CLAMP(pvalue, -1.0f, 1.0f); \
4240 } \
4241 (void)0
4242
4243static void get_cpa_texture(Mesh *mesh,
4244 ParticleSystem *psys,
4245 ParticleSettings *part,
4246 ParticleData *par,
4247 int child_index,
4248 int face_index,
4249 const float fw[4],
4250 float *orco,
4251 ParticleTexture *ptex,
4252 int event,
4253 float cfra)
4254{
4255 MTex *mtex, **mtexp = part->mtex;
4256 int m;
4257 float value, rgba[4], texvec[3];
4258
4259 ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = ptex->gravity = ptex->field =
4260 ptex->time = ptex->clump = ptex->kink_freq = ptex->kink_amp = ptex->effector = ptex->rough1 =
4261 ptex->rough2 = ptex->roughe = 1.0f;
4262 ptex->twist = 1.0f;
4263
4264 ptex->length = 1.0f - part->randlength * psys_frand(psys, child_index + 26);
4265 ptex->length *= part->clength_thres < psys_frand(psys, child_index + 27) ? part->clength : 1.0f;
4266
4267 for (m = 0; m < MAX_MTEX; m++, mtexp++) {
4268 mtex = *mtexp;
4269 if (mtex && mtex->tex && mtex->mapto) {
4270 float def = mtex->def_var;
4271 short blend = mtex->blendtype;
4272 short texco = mtex->texco;
4273
4274 if (ELEM(texco, TEXCO_UV, TEXCO_ORCO) &&
4275 (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 ||
4276 part->distr == PART_DISTR_GRID))
4277 {
4278 texco = TEXCO_GLOB;
4279 }
4280
4281 switch (texco) {
4282 case TEXCO_GLOB:
4283 copy_v3_v3(texvec, par->state.co);
4284 break;
4285 case TEXCO_OBJECT:
4286 copy_v3_v3(texvec, par->state.co);
4287 if (mtex->object) {
4288 mul_m4_v3(mtex->object->world_to_object().ptr(), texvec);
4289 }
4290 break;
4291 case TEXCO_UV:
4292 if (fw && get_particle_uv(mesh,
4293 nullptr,
4294 face_index,
4295 fw,
4296 mtex->uvname,
4297 texvec,
4298 (part->from == PART_FROM_VERT)))
4299 {
4300 break;
4301 }
4302 /* no break, failed to get uv's, so let's try orco's */
4304 case TEXCO_ORCO:
4305 copy_v3_v3(texvec, orco);
4306 break;
4307 case TEXCO_PARTICLE:
4308 /* texture coordinates in range [-1, 1] */
4309 texvec[0] = 2.0f * (cfra - par->time) / (par->dietime - par->time) - 1.0f;
4310 texvec[1] = 0.0f;
4311 texvec[2] = 0.0f;
4312 break;
4313 }
4314
4315 RE_texture_evaluate(mtex, texvec, 0, nullptr, false, false, &value, rgba);
4316
4317 if ((event & mtex->mapto) & PAMAP_ROUGH) {
4318 ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend(
4319 def, ptex->rough1, value, mtex->roughfac, blend);
4320 }
4321
4328 }
4329 }
4330
4337}
4339 ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra)
4340{
4341 Object *ob = sim->ob;
4342 Mesh *mesh = (Mesh *)ob->data;
4343 ParticleSettings *part = sim->psys->part;
4344 MTex **mtexp = part->mtex;
4345 MTex *mtex;
4346 int m;
4347 float value, rgba[4], co[3], texvec[3];
4348 int setvars = 0;
4349
4350 /* initialize ptex */
4351 ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = ptex->gravity = ptex->field =
4352 ptex->length = ptex->clump = ptex->kink_freq = ptex->kink_amp = ptex->effector =
4353 ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
4354 ptex->twist = 1.0f;
4355
4356 ptex->time = float(pa - sim->psys->particles) / float(sim->psys->totpart);
4357
4358 for (m = 0; m < MAX_MTEX; m++, mtexp++) {
4359 mtex = *mtexp;
4360 if (mtex && mtex->tex && mtex->mapto) {
4361 float def = mtex->def_var;
4362 short blend = mtex->blendtype;
4363 short texco = mtex->texco;
4364
4365 if (texco == TEXCO_UV && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 ||
4366 part->distr == PART_DISTR_GRID))
4367 {
4368 texco = TEXCO_GLOB;
4369 }
4370
4371 switch (texco) {
4372 case TEXCO_GLOB:
4373 copy_v3_v3(texvec, pa->state.co);
4374 break;
4375 case TEXCO_OBJECT:
4376 copy_v3_v3(texvec, pa->state.co);
4377 if (mtex->object) {
4378 mul_m4_v3(mtex->object->world_to_object().ptr(), texvec);
4379 }
4380 break;
4381 case TEXCO_UV:
4383 pa,
4384 0,
4385 pa->fuv,
4386 mtex->uvname,
4387 texvec,
4388 (part->from == PART_FROM_VERT)))
4389 {
4390 break;
4391 }
4392 /* no break, failed to get uv's, so let's try orco's */
4394 case TEXCO_ORCO:
4396 sim->psys->part->from,
4397 pa->num,
4398 pa->num_dmcache,
4399 pa->fuv,
4400 pa->foffset,
4401 co,
4402 nullptr,
4403 nullptr,
4404 nullptr,
4405 texvec);
4406
4408 sub_v3_v3(texvec, mesh->texspace_location);
4409 if (mesh->texspace_size[0] != 0.0f) {
4410 texvec[0] /= mesh->texspace_size[0];
4411 }
4412 if (mesh->texspace_size[1] != 0.0f) {
4413 texvec[1] /= mesh->texspace_size[1];
4414 }
4415 if (mesh->texspace_size[2] != 0.0f) {
4416 texvec[2] /= mesh->texspace_size[2];
4417 }
4418 break;
4419 case TEXCO_PARTICLE:
4420 /* texture coordinates in range [-1, 1] */
4421 texvec[0] = 2.0f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.0f;
4422 if (sim->psys->totpart > 0) {
4423 texvec[1] = 2.0f * float(pa - sim->psys->particles) / float(sim->psys->totpart) - 1.0f;
4424 }
4425 else {
4426 texvec[1] = 0.0f;
4427 }
4428 texvec[2] = 0.0f;
4429 break;
4430 }
4431
4432 RE_texture_evaluate(mtex, texvec, 0, nullptr, false, false, &value, rgba);
4433
4434 if ((event & mtex->mapto) & PAMAP_TIME) {
4435 /* the first time has to set the base value for time regardless of blend mode */
4436 if ((setvars & PAMAP_TIME) == 0) {
4437 int flip = (mtex->timefac < 0.0f);
4438 float timefac = fabsf(mtex->timefac);
4439 ptex->time *= 1.0f - timefac;
4440 ptex->time += timefac * ((flip) ? 1.0f - value : value);
4441 setvars |= PAMAP_TIME;
4442 }
4443 else {
4444 ptex->time = texture_value_blend(def, ptex->time, value, mtex->timefac, blend);
4445 }
4446 }
4456 }
4457 }
4458
4468}
4469
4470/************************************************/
4471/* Particle State */
4472/************************************************/
4473
4475{
4476 return 0.04f * sim->psys->part->timetweak;
4477}
4479 ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
4480{
4481 ParticleSettings *part = psys->part;
4482 float time, life;
4483
4484 if (part->childtype == PART_CHILD_FACES) {
4485 int w = 0;
4486 time = 0.0;
4487 while (w < 4 && cpa->pa[w] >= 0) {
4488 time += cpa->w[w] * (psys->particles + cpa->pa[w])->time;
4489 w++;
4490 }
4491
4492 life = part->lifetime * (1.0f - part->randlife * psys_frand(psys, cpa - psys->child + 25));
4493 }
4494 else {
4495 ParticleData *pa = psys->particles + cpa->parent;
4496
4497 time = pa->time;
4498 life = pa->lifetime;
4499 }
4500
4501 if (birthtime) {
4502 *birthtime = time;
4503 }
4504 if (dietime) {
4505 *dietime = time + life;
4506 }
4507
4508 return (cfra - time) / life;
4509}
4511 ChildParticle *cpa,
4512 float /*cfra*/,
4513 float * /*pa_time*/)
4514{
4515 ParticleSettings *part = psys->part;
4516 float size; /* time XXX */
4517
4518 if (part->childtype == PART_CHILD_FACES) {
4519 int w = 0;
4520 size = 0.0;
4521 while (w < 4 && cpa->pa[w] >= 0) {
4522 size += cpa->w[w] * (psys->particles + cpa->pa[w])->size;
4523 w++;
4524 }
4525 }
4526 else {
4527 size = psys->particles[cpa->parent].size;
4528 }
4529
4530 size *= part->childsize;
4531
4532 if (part->childrandsize != 0.0f) {
4533 size *= 1.0f - part->childrandsize * psys_frand(psys, cpa - psys->child + 26);
4534 }
4535
4536 return size;
4537}
4540 ChildParticle *cpa,
4541 short cpa_from,
4542 int cpa_num,
4543 float *cpa_fuv,
4544 float *orco,
4545 ParticleTexture *ptex)
4546{
4547 ParticleSystem *psys = ctx->sim.psys;
4548 int i = cpa - psys->child;
4549
4550 get_cpa_texture(ctx->mesh,
4551 psys,
4552 part,
4553 psys->particles + cpa->pa[0],
4554 i,
4555 cpa_num,
4556 cpa_fuv,
4557 orco,
4558 ptex,
4560 psys->cfra);
4561
4562 if (ptex->exist < psys_frand(psys, i + 24)) {
4563 return;
4564 }
4565
4566 if (ctx->vg_length) {
4568 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_length);
4569 }
4570 if (ctx->vg_clump) {
4572 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_clump);
4573 }
4574 if (ctx->vg_kink) {
4576 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_kink);
4577 }
4578 if (ctx->vg_rough1) {
4580 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough1);
4581 }
4582 if (ctx->vg_rough2) {
4584 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough2);
4585 }
4586 if (ctx->vg_roughe) {
4588 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_roughe);
4589 }
4590 if (ctx->vg_effector) {
4592 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_effector);
4593 }
4594 if (ctx->vg_twist) {
4596 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_twist);
4597 }
4598}
4600 int p,
4602 const bool vel)
4603{
4605 ParticleSystem *psys = sim->psys;
4606 ParticleSettings *part = sim->psys->part;
4607 Material *ma = BKE_object_material_get(sim->ob, part->omat);
4608 ParticleData *pa;
4609 ChildParticle *cpa;
4610 ParticleTexture ptex;
4611 ParticleKey *par = nullptr, keys[4], tstate;
4612 ParticleThreadContext ctx; /* fake thread context for child modifiers */
4614
4615 float t;
4616 float co[3], orco[3];
4617 float hairmat[4][4];
4618 int totpart = psys->totpart;
4619 int totchild = psys->totchild;
4620 short between = 0, edit = 0;
4621
4622 int keyed = part->phystype & PART_PHYS_KEYED && psys->flag & PSYS_KEYED;
4623 int cached = !keyed && part->type != PART_HAIR;
4624
4625 float *cpa_fuv;
4626 int cpa_num;
4627 short cpa_from;
4628
4629 /* initialize keys to zero */
4630 memset(keys, 0, sizeof(ParticleKey[4]));
4631
4632 t = state->time;
4633 CLAMP(t, 0.0f, 1.0f);
4634
4635 if (p < totpart) {
4636 /* interpolate pathcache directly if it exist */
4637 if (psys->pathcache) {
4639 interpolate_pathcache(psys->pathcache[p], t, &result);
4640 copy_v3_v3(state->co, result.co);
4641 copy_v3_v3(state->vel, result.vel);
4642 copy_qt_qt(state->rot, result.rot);
4643 }
4644 /* otherwise interpolate with other means */
4645 else {
4646 pa = psys->particles + p;
4647
4648 pind.keyed = keyed;
4649 pind.cache = cached ? psys->pointcache : nullptr;
4650 pind.epoint = nullptr;
4651 pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
4652 /* `pind.dm` disabled in edit-mode means we don't get effectors taken into
4653 * account when subdividing for instance. */
4654 pind.mesh = psys_in_edit_mode(sim->depsgraph, psys) ?
4655 nullptr :
4656 psys->hair_out_mesh; /* XXX(@sybren): EEK. */
4657 init_particle_interpolation(sim->ob, psys, pa, &pind);
4658 do_particle_interpolation(psys, p, pa, t, &pind, state);
4659
4660 if (pind.mesh) {
4661 mul_m4_v3(sim->ob->object_to_world().ptr(), state->co);
4662 mul_mat3_m4_v3(sim->ob->object_to_world().ptr(), state->vel);
4663 }
4664 else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
4665 if ((pa->flag & PARS_REKEY) == 0) {
4666 psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, part->from, pa, hairmat);
4667 mul_m4_v3(hairmat, state->co);
4668 mul_mat3_m4_v3(hairmat, state->vel);
4669
4670 if (sim->psys->effectors && (part->flag & PART_CHILD_GUIDE) == 0) {
4671 do_guides(
4672 sim->depsgraph, sim->psys->part, sim->psys->effectors, state, p, state->time);
4673 /* TODO: proper velocity handling */
4674 }
4675
4676 if (psys->lattice_deform_data && edit == 0) {
4678 psys->lattice_deform_data, state->co, psys->lattice_strength);
4679 }
4680 }
4681 }
4682 }
4683 }
4684 else if (totchild) {
4685 // invert_m4_m4(imat, ob->object_to_world().ptr());
4686
4687 /* interpolate childcache directly if it exists */
4688 if (psys->childcache) {
4690 interpolate_pathcache(psys->childcache[p - totpart], t, &result);
4691 copy_v3_v3(state->co, result.co);
4692 copy_v3_v3(state->vel, result.vel);
4693 copy_qt_qt(state->rot, result.rot);
4694 }
4695 else {
4696 float par_co[3], par_orco[3];
4697
4698 cpa = psys->child + p - totpart;
4699
4700 if (state->time < 0.0f) {
4701 t = psys_get_child_time(psys, cpa, -state->time, nullptr, nullptr);
4702 }
4703
4704 if (part->childtype == PART_CHILD_FACES) {
4705 /* part->parents could still be 0 so we can't test with totparent */
4706 between = 1;
4707 }
4708 if (between) {
4709 int w = 0;
4710 float foffset;
4711
4712 /* get parent states */
4713 while (w < 4 && cpa->pa[w] >= 0) {
4714 keys[w].time = state->time;
4715 psys_get_particle_on_path(sim, cpa->pa[w], keys + w, true);
4716 w++;
4717 }
4718
4719 /* get the original coordinates (orco) for texture usage */
4720 cpa_num = cpa->num;
4721
4722 foffset = cpa->foffset;
4723 cpa_fuv = cpa->fuv;
4724 cpa_from = PART_FROM_FACE;
4725
4727 cpa_from,
4728 cpa_num,
4730 cpa->fuv,
4731 foffset,
4732 co,
4733 nullptr,
4734 nullptr,
4735 nullptr,
4736 orco);
4737
4738 /* We need to save the actual root position of the child for
4739 * positioning it accurately to the surface of the emitter. */
4740 // copy_v3_v3(cpa_1st, co);
4741
4742 // mul_m4_v3(ob->object_to_world().ptr(), cpa_1st);
4743
4744 pa = psys->particles + cpa->parent;
4745
4747 part->from,
4748 pa->num,
4749 pa->num_dmcache,
4750 pa->fuv,
4751 pa->foffset,
4752 par_co,
4753 nullptr,
4754 nullptr,
4755 nullptr,
4756 par_orco);
4757 if (part->type == PART_HAIR) {
4758 psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
4759 }
4760 else {
4761 unit_m4(hairmat);
4762 }
4763
4764 pa = nullptr;
4765 }
4766 else {
4767 /* get the parent state */
4768 keys->time = state->time;
4769 psys_get_particle_on_path(sim, cpa->parent, keys, true);
4770
4771 /* get the original coordinates (orco) for texture usage */
4772 pa = psys->particles + cpa->parent;
4773
4774 cpa_from = part->from;
4775 cpa_num = pa->num;
4776 cpa_fuv = pa->fuv;
4777
4779 part->from,
4780 pa->num,
4781 pa->num_dmcache,
4782 pa->fuv,
4783 pa->foffset,
4784 par_co,
4785 nullptr,
4786 nullptr,
4787 nullptr,
4788 par_orco);
4789 if (part->type == PART_HAIR) {
4791 cpa_from,
4792 cpa_num,
4794 cpa_fuv,
4795 pa->foffset,
4796 co,
4797 nullptr,
4798 nullptr,
4799 nullptr,
4800 orco);
4801 psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
4802 }
4803 else {
4804 copy_v3_v3(orco, cpa->fuv);
4805 unit_m4(hairmat);
4806 }
4807 }
4808
4809 /* get different child parameters from textures & vgroups */
4810 memset(&ctx, 0, sizeof(ParticleThreadContext));
4811 ctx.sim = *sim;
4812 ctx.mesh = psmd->mesh_final;
4813 ctx.ma = ma;
4814 /* TODO: assign vertex groups */
4815 get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
4816
4817 if (between) {
4818 int w = 0;
4819
4820 state->co[0] = state->co[1] = state->co[2] = 0.0f;
4821 state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
4822
4823 /* child position is the weighted sum of parent positions */
4824 while (w < 4 && cpa->pa[w] >= 0) {
4825 state->co[0] += cpa->w[w] * keys[w].co[0];
4826 state->co[1] += cpa->w[w] * keys[w].co[1];
4827 state->co[2] += cpa->w[w] * keys[w].co[2];
4828
4829 state->vel[0] += cpa->w[w] * keys[w].vel[0];
4830 state->vel[1] += cpa->w[w] * keys[w].vel[1];
4831 state->vel[2] += cpa->w[w] * keys[w].vel[2];
4832 w++;
4833 }
4834 /* apply offset for correct positioning */
4835 // add_v3_v3(state->co, cpa_1st);
4836 }
4837 else {
4838 /* offset the child from the parent position */
4839 offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad);
4840 }
4841
4842 par = keys;
4843
4844 if (vel) {
4845 copy_particle_key(&tstate, state, 1);
4846 }
4847
4848 /* apply different deformations to the child path */
4849 ParticleChildModifierContext modifier_ctx = {nullptr};
4850 modifier_ctx.thread_ctx = nullptr;
4851 modifier_ctx.sim = sim;
4852 modifier_ctx.ptex = &ptex;
4853 modifier_ctx.cpa = cpa;
4854 modifier_ctx.orco = orco;
4855 modifier_ctx.par_co = par->co;
4856 modifier_ctx.par_vel = par->vel;
4857 modifier_ctx.par_rot = par->rot;
4858 modifier_ctx.par_orco = par_orco;
4859 modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : nullptr;
4860 do_child_modifiers(&modifier_ctx, hairmat, state, t);
4861
4862 /* try to estimate correct velocity */
4863 if (vel) {
4864 ParticleKey tstate_tmp;
4865 float length = len_v3(state->vel);
4866
4867 if (t >= 0.001f) {
4868 tstate_tmp.time = t - 0.001f;
4869 psys_get_particle_on_path(sim, p, &tstate_tmp, false);
4870 sub_v3_v3v3(state->vel, state->co, tstate_tmp.co);
4871 normalize_v3(state->vel);
4872 }
4873 else {
4874 tstate_tmp.time = t + 0.001f;
4875 psys_get_particle_on_path(sim, p, &tstate_tmp, false);
4876 sub_v3_v3v3(state->vel, tstate_tmp.co, state->co);
4877 normalize_v3(state->vel);
4878 }
4879
4880 mul_v3_fl(state->vel, length);
4881 }
4882 }
4883 }
4884}
4885
4887 int p,
4889 const bool always)
4890{
4891 ParticleSystem *psys = sim->psys;
4892 ParticleSettings *part = psys->part;
4893 ParticleData *pa = nullptr;
4894 ChildParticle *cpa = nullptr;
4895 float cfra;
4896 int totpart = psys->totpart;
4897 float timestep = psys_get_timestep(sim);
4898
4899 /* negative time means "use current time" */
4900 cfra = state->time > 0 ? state->time : DEG_get_ctime(sim->depsgraph);
4901
4902 if (p >= totpart) {
4903 if (!psys->totchild) {
4904 return false;
4905 }
4906
4907 if (part->childtype == PART_CHILD_FACES) {
4908 if (!(psys->flag & PSYS_KEYED)) {
4909 return false;
4910 }
4911
4912 cpa = psys->child + p - totpart;
4913
4914 state->time = psys_get_child_time(psys, cpa, cfra, nullptr, nullptr);
4915
4916 if (!always) {
4917 if ((state->time < 0.0f && !(part->flag & PART_UNBORN)) ||
4918 (state->time > 1.0f && !(part->flag & PART_DIED)))
4919 {
4920 return false;
4921 }
4922 }
4923
4924 state->time = (cfra - (part->sta + (part->end - part->sta) * psys_frand(psys, p + 23))) /
4925 (part->lifetime * psys_frand(psys, p + 24));
4926
4927 psys_get_particle_on_path(sim, p, state, true);
4928 return true;
4929 }
4930
4931 cpa = sim->psys->child + p - totpart;
4932 pa = sim->psys->particles + cpa->parent;
4933 }
4934 else {
4935 pa = sim->psys->particles + p;
4936 }
4937
4938 if (pa) {
4939 if (!always) {
4940 if ((cfra < pa->time && (part->flag & PART_UNBORN) == 0) ||
4941 (cfra >= pa->dietime && (part->flag & PART_DIED) == 0))
4942 {
4943 return false;
4944 }
4945 }
4946
4947 cfra = std::min(cfra, pa->dietime);
4948 }
4949
4950 if (sim->psys->flag & PSYS_KEYED) {
4951 state->time = -cfra;
4952 psys_get_particle_on_path(sim, p, state, true);
4953 return true;
4954 }
4955
4956 if (cpa) {
4957 float mat[4][4];
4958 ParticleKey *key1;
4959 float t = (cfra - pa->time) / pa->lifetime;
4960 const float par_orco[3] = {0.0f, 0.0f, 0.0f};
4961
4962 key1 = &pa->state;
4963 offset_child(cpa, key1, key1->rot, state, part->childflat, part->childrad);
4964
4965 CLAMP(t, 0.0f, 1.0f);
4966
4967 unit_m4(mat);
4968 ParticleChildModifierContext modifier_ctx = {nullptr};
4969 modifier_ctx.thread_ctx = nullptr;
4970 modifier_ctx.sim = sim;
4971 modifier_ctx.ptex = nullptr;
4972 modifier_ctx.cpa = cpa;
4973 modifier_ctx.orco = cpa->fuv;
4974 modifier_ctx.par_co = key1->co;
4975 modifier_ctx.par_vel = key1->vel;
4976 modifier_ctx.par_rot = key1->rot;
4977 modifier_ctx.par_orco = par_orco;
4978 modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : nullptr;
4979
4980 do_child_modifiers(&modifier_ctx, mat, state, t);
4981
4982 if (psys->lattice_deform_data) {
4984 psys->lattice_deform_data, state->co, psys->lattice_strength);
4985 }
4986 }
4987 else {
4988 if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
4989 copy_particle_key(state, &pa->state, 1);
4990 }
4991 else if (pa->prev_state.time == cfra) {
4993 }
4994 else {
4995 float dfra, frs_sec = sim->scene->r.frs_sec;
4996 /* let's interpolate to try to be as accurate as possible */
4997 if (pa->state.time + 2.0f >= state->time && pa->prev_state.time - 2.0f <= state->time) {
4998 if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.0f) {
4999 /* prev_state is wrong so let's not use it,
5000 * this can happen at frames 1, 0 or particle birth. */
5001 dfra = state->time - pa->state.time;
5002
5003 copy_particle_key(state, &pa->state, 1);
5004
5005 madd_v3_v3v3fl(state->co, state->co, state->vel, dfra / frs_sec);
5006 }
5007 else {
5008 ParticleKey keys[4];
5009 float keytime;
5010
5011 copy_particle_key(keys + 1, &pa->prev_state, 1);
5012 copy_particle_key(keys + 2, &pa->state, 1);
5013
5014 dfra = keys[2].time - keys[1].time;
5015
5016 keytime = (state->time - keys[1].time) / dfra;
5017
5018 /* convert velocity to timestep size */
5019 mul_v3_fl(keys[1].vel, dfra * timestep);
5020 mul_v3_fl(keys[2].vel, dfra * timestep);
5021
5022 psys_interpolate_particle(-1, keys, keytime, state, true);
5023
5024 /* convert back to real velocity */
5025 mul_v3_fl(state->vel, 1.0f / (dfra * timestep));
5026
5027 interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime);
5028 interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime);
5029 }
5030 }
5031 else if (pa->state.time + 1.0f >= state->time && pa->state.time - 1.0f <= state->time) {
5032 /* linear interpolation using only pa->state */
5033
5034 dfra = state->time - pa->state.time;
5035
5036 copy_particle_key(state, &pa->state, 1);
5037
5038 madd_v3_v3v3fl(state->co, state->co, state->vel, dfra / frs_sec);
5039 }
5040 else {
5041 /* Extrapolating over big ranges is not accurate
5042 * so let's just give something close to reasonable back. */
5043 copy_particle_key(state, &pa->state, 0);
5044 }
5045 }
5046
5047 if (sim->psys->lattice_deform_data) {
5050 }
5051 }
5052
5053 return true;
5054}
5055
5057 ParticleSettings *part,
5059 ParticleData *pa,
5060 ChildParticle *cpa,
5061 float uv[2],
5062 float orco[3])
5063{
5064 float loc[3];
5065 int num;
5066
5067 /* XXX: on checking '(psmd->dm != nullptr)'
5068 * This is incorrect but needed for meta-ball evaluation.
5069 * Ideally this would be calculated via the depsgraph, however with meta-balls,
5070 * the entire scenes dupli's are scanned, which also looks into uncalculated data.
5071 *
5072 * For now just include this workaround as an alternative to crashing,
5073 * but longer term meta-balls should behave in a more manageable way, see: #46622. */
5074
5075 uv[0] = uv[1] = 0.0f;
5076
5077 /* Grid distribution doesn't support UV or emit from vertex mode */
5078 bool is_grid = (part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT);
5079
5080 if (cpa) {
5081 if ((part->childtype == PART_CHILD_FACES) && (psmd->mesh_final != nullptr)) {
5082 if (!is_grid) {
5083 CustomData *mtf_data = &psmd->mesh_final->fdata_legacy;
5084 const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
5085
5086 if (uv_idx >= 0) {
5087 const MTFace *mtface = static_cast<const MTFace *>(
5088 CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx));
5089 if (mtface != nullptr) {
5090 const MFace *mface = static_cast<const MFace *>(
5092 cpa->num,
5093 CD_MFACE,
5094 psmd->mesh_final->totface_legacy));
5095 mtface += cpa->num;
5096 psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
5097 }
5098 }
5099 }
5100
5103 cpa->num,
5105 cpa->fuv,
5106 cpa->foffset,
5107 loc,
5108 nullptr,
5109 nullptr,
5110 nullptr,
5111 orco);
5112 return;
5113 }
5114
5115 pa = psys->particles + cpa->pa[0];
5116 }
5117
5118 if ((part->from == PART_FROM_FACE) && (psmd->mesh_final != nullptr) && !is_grid) {
5119 num = pa->num_dmcache;
5120
5121 if (num == DMCACHE_NOTFOUND) {
5122 num = pa->num;
5123 }
5124
5125 if (num >= psmd->mesh_final->totface_legacy) {
5126 /* happens when simplify is enabled
5127 * gives invalid coords but would crash otherwise */
5128 num = DMCACHE_NOTFOUND;
5129 }
5130
5132 CustomData *mtf_data = &psmd->mesh_final->fdata_legacy;
5133 const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
5134
5135 if (uv_idx >= 0) {
5136 const MTFace *mtface = static_cast<const MTFace *>(
5137 CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx));
5138 const MFace *mface = static_cast<const MFace *>(CustomData_get_for_write(
5140 mtface += num;
5141 psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
5142 }
5143 }
5144 }
5145
5147 part->from,
5148 pa->num,
5149 pa->num_dmcache,
5150 pa->fuv,
5151 pa->foffset,
5152 loc,
5153 nullptr,
5154 nullptr,
5155 nullptr,
5156 orco);
5157}
5158
5160 ParticleData *pa,
5161 ChildParticle *cpa,
5162 ParticleCacheKey *cache,
5163 float mat[4][4],
5164 float *scale)
5165{
5166 Object *ob = sim->ob;
5167 ParticleSystem *psys = sim->psys;
5168 ParticleSystemModifierData *psmd = sim->psmd;
5169 float loc[3], nor[3], vec[3], side[3], len;
5170 float xvec[3] = {-1.0, 0.0, 0.0}, nmat[3][3];
5171
5172 sub_v3_v3v3(vec, (cache + cache->segments)->co, cache->co);
5173 len = normalize_v3(vec);
5174
5175 if (pa == nullptr && psys->part->childflat != PART_CHILD_FACES) {
5176 pa = psys->particles + cpa->pa[0];
5177 }
5178
5179 if (pa) {
5181 sim->psys->part->from,
5182 pa->num,
5183 pa->num_dmcache,
5184 pa->fuv,
5185 pa->foffset,
5186 loc,
5187 nor,
5188 nullptr,
5189 nullptr,
5190 nullptr);
5191 }
5192 else {
5195 cpa->num,
5197 cpa->fuv,
5198 cpa->foffset,
5199 loc,
5200 nor,
5201 nullptr,
5202 nullptr,
5203 nullptr);
5204 }
5205
5206 if (psys->part->rotmode == PART_ROT_VEL) {
5207 transpose_m3_m4(nmat, ob->world_to_object().ptr());
5208 mul_m3_v3(nmat, nor);
5210
5211 /* make sure that we get a proper side vector */
5212 if (fabsf(dot_v3v3(nor, vec)) > 0.999999f) {
5213 if (fabsf(dot_v3v3(nor, xvec)) > 0.999999f) {
5214 nor[0] = 0.0f;
5215 nor[1] = 1.0f;
5216 nor[2] = 0.0f;
5217 }
5218 else {
5219 nor[0] = 1.0f;
5220 nor[1] = 0.0f;
5221 nor[2] = 0.0f;
5222 }
5223 }
5224 cross_v3_v3v3(side, nor, vec);
5225 normalize_v3(side);
5226
5227 /* rotate side vector around vec */
5228 if (psys->part->phasefac != 0) {
5229 float q_phase[4];
5230 float phasefac = psys->part->phasefac;
5231 if (psys->part->randphasefac != 0.0f) {
5232 phasefac += psys->part->randphasefac * psys_frand(psys, (pa - psys->particles) + 20);
5233 }
5234 axis_angle_to_quat(q_phase, vec, phasefac * float(M_PI));
5235
5236 mul_qt_v3(q_phase, side);
5237 }
5238
5239 cross_v3_v3v3(nor, vec, side);
5240
5241 unit_m4(mat);
5242 copy_v3_v3(mat[0], vec);
5243 copy_v3_v3(mat[1], side);
5244 copy_v3_v3(mat[2], nor);
5245 }
5246 else {
5247 quat_to_mat4(mat, pa->state.rot);
5248 }
5249
5250 *scale = len;
5251}
5252
5254{
5255 ParticleSimulationData sim = {nullptr};
5256 sim.depsgraph = depsgraph;
5257 sim.scene = scene;
5258 sim.ob = ob;
5259 sim.psys = psys;
5260 sim.psmd = psys_get_modifier(ob, psys);
5261
5262 psys_sim_data_init(&sim);
5263
5264 if (psys->lattice_deform_data) {
5265 ParticleData *pa = psys->particles;
5266 HairKey *hkey;
5267 int p, h;
5268 float hairmat[4][4], imat[4][4];
5269
5270 for (p = 0; p < psys->totpart; p++, pa++) {
5271 psys_mat_hair_to_global(sim.ob, sim.psmd->mesh_final, psys->part->from, pa, hairmat);
5272 invert_m4_m4(imat, hairmat);
5273
5274 hkey = pa->hair;
5275 for (h = 0; h < pa->totkey; h++, hkey++) {
5276 mul_m4_v3(hairmat, hkey->co);
5278 psys->lattice_deform_data, hkey->co, psys->lattice_strength);
5279 mul_m4_v3(imat, hkey->co);
5280 }
5281 }
5282
5283 /* protect the applied shape */
5284 psys->flag |= PSYS_EDITED;
5285 }
5286
5287 psys_sim_data_free(&sim);
5288}
5289
5290/* Draw Engine */
5291
5294
5296{
5297 if (psys->batch_cache) {
5299 }
5300}
5302{
5303 if (psys->batch_cache) {
5305 }
5306}
5307
5309{
5310 LISTBASE_FOREACH (ParticleSystem *, psys, particles) {
5311 BLO_write_struct(writer, ParticleSystem, psys);
5312
5313 if (psys->particles) {
5315
5316 if (psys->particles->hair) {
5317 ParticleData *pa = psys->particles;
5318
5319 for (int a = 0; a < psys->totpart; a++, pa++) {
5320 BLO_write_struct_array(writer, HairKey, pa->totkey, pa->hair);
5321 }
5322 }
5323
5324 if (psys->particles->boid && (psys->part->phystype == PART_PHYS_BOIDS)) {
5326 }
5327
5328 if (psys->part->fluid && (psys->part->phystype == PART_PHYS_FLUID) &&
5330 {
5332 writer, ParticleSpring, psys->tot_fluidsprings, psys->fluid_springs);
5333 }
5334 }
5335 LISTBASE_FOREACH (ParticleTarget *, pt, &psys->targets) {
5336 BLO_write_struct(writer, ParticleTarget, pt);
5337 }
5338
5339 if (psys->child) {
5340 BLO_write_struct_array(writer, ChildParticle, psys->totchild, psys->child);
5341 }
5342
5343 if (psys->clmd) {
5344 BLO_write_struct(writer, ClothModifierData, psys->clmd);
5347 }
5348
5349 BKE_ptcache_blend_write(writer, &psys->ptcaches);
5350 }
5351}
5352
5354{
5355 ParticleData *pa;
5356 int a;
5357
5358 LISTBASE_FOREACH (ParticleSystem *, psys, particles) {
5359 BLO_read_struct_array(reader, ParticleData, psys->totpart, &psys->particles);
5360
5361 if (psys->particles && psys->particles->hair) {
5362 for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) {
5363 BLO_read_struct_array(reader, HairKey, pa->totkey, &pa->hair);
5364 }
5365 }
5366
5367 if (psys->particles && psys->particles->keys) {
5368 for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) {
5369 pa->keys = nullptr;
5370 pa->totkey = 0;
5371 }
5372
5373 psys->flag &= ~PSYS_KEYED;
5374 }
5375
5376 if (psys->particles && psys->particles->boid) {
5377 pa = psys->particles;
5378 BLO_read_struct_array(reader, BoidParticle, psys->totpart, &pa->boid);
5379
5380 /* This is purely runtime data, but still can be an issue if left dangling. */
5381 pa->boid->ground = nullptr;
5382
5383 for (a = 1, pa++; a < psys->totpart; a++, pa++) {
5384 pa->boid = (pa - 1)->boid + 1;
5385 pa->boid->ground = nullptr;
5386 }
5387 }
5388 else if (psys->particles) {
5389 for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) {
5390 pa->boid = nullptr;
5391 }
5392 }
5393
5395
5396 BLO_read_struct_array(reader, ChildParticle, psys->totchild, &psys->child);
5397 psys->effectors = nullptr;
5398
5400
5401 psys->edit = nullptr;
5402 psys->free_edit = nullptr;
5403 psys->pathcache = nullptr;
5404 psys->childcache = nullptr;
5407 psys->pdd = nullptr;
5408
5409 if (psys->clmd) {
5410 BLO_read_struct(reader, ClothModifierData, &psys->clmd);
5411 psys->clmd->clothObject = nullptr;
5412 psys->clmd->hairdata = nullptr;
5413
5416
5417 if (psys->clmd->sim_parms) {
5418 psys->clmd->sim_parms->effector_weights = nullptr;
5419 if (psys->clmd->sim_parms->presets > 10) {
5420 psys->clmd->sim_parms->presets = 0;
5421 }
5422 }
5423
5424 psys->hair_in_mesh = psys->hair_out_mesh = nullptr;
5425 psys->clmd->solver_result = nullptr;
5426 }
5427
5428 BKE_ptcache_blend_read_data(reader, &psys->ptcaches, &psys->pointcache, 0);
5429 if (psys->clmd) {
5430 psys->clmd->point_cache = psys->pointcache;
5431 }
5432
5433 psys->tree = nullptr;
5434 psys->bvhtree = nullptr;
5435
5436 psys->orig_psys = nullptr;
5437 psys->batch_cache = nullptr;
5438 }
5439}
5440
5442 Object *ob,
5443 ID * /*id*/,
5444 ListBase *particles)
5445{
5446 LISTBASE_FOREACH_MUTABLE (ParticleSystem *, psys, particles) {
5447 if (psys->part) {
5448 if (psys->clmd) {
5449 /* XXX(@ideasman42): from reading existing code this seems correct but intended usage
5450 * of point-cache with cloth should be added in #ParticleSystem. */
5451 psys->clmd->point_cache = psys->pointcache;
5452 psys->clmd->ptcaches.first = psys->clmd->ptcaches.last = nullptr;
5453 psys->clmd->modifier.error = nullptr;
5454 }
5455 }
5456 else {
5457 /* Particle modifier must be removed before particle system. */
5461
5462 BLI_remlink(particles, psys);
5463 MEM_freeN(psys);
5464 }
5465 }
5466}
bool BKE_where_on_path(const struct Object *ob, float ctime, float r_vec[4], float r_dir[3], float r_quat[4], float *r_radius, float *r_weight)
struct BoidSettings * boid_copy_settings(const struct BoidSettings *boids)
void boid_free_settings(struct BoidSettings *boids)
Definition boids.cc:1683
void cloth_free_modifier(ClothModifierData *clmd)
Definition cloth.cc:433
bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
ListBase BKE_collection_object_cache_get(Collection *collection)
void BKE_curvemapping_changed_all(CurveMapping *cumap)
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
CurveMapping * BKE_curvemapping_copy(const CurveMapping *cumap)
void BKE_curvemapping_init(CurveMapping *cumap)
CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition colortools.cc:90
void BKE_curvemapping_free(CurveMapping *cumap)
void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap)
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer_n(const CustomData *data, eCustomDataType type, int n)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
int CustomData_get_render_layer(const CustomData *data, eCustomDataType type)
void * CustomData_get_for_write(CustomData *data, int index, eCustomDataType type, int totelem)
support for deformation groups and hooks.
void BKE_defvert_weight_to_rgb(float r_rgb[3], float weight)
Definition deform.cc:1596
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:770
display list (or rather multi purpose list) stuff.
float BKE_displist_calc_taper(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *taperobj, int cur, int tot)
void BKE_partdeflect_free(struct PartDeflect *pd)
Definition effect.cc:119
struct PartDeflect * BKE_partdeflect_new(int type)
Definition effect.cc:71
struct EffectorWeights * BKE_effector_add_weights(struct Collection *collection)
Definition effect.cc:57
float effector_falloff(struct EffectorCache *eff, struct EffectorData *efd, struct EffectedPoint *point, struct EffectorWeights *weights)
Definition effect.cc:589
void BKE_effectors_free(struct ListBase *lb)
Definition effect.cc:364
void BKE_effectors_apply(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *wind_force, float *impulse)
Definition effect.cc:1110
struct PartDeflect * BKE_partdeflect_copy(const struct PartDeflect *pd_src)
void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point)
Definition effect.cc:381
void key_curve_position_weights(float t, float data[4], int type)
Definition key.cc:339
LatticeDeformData * BKE_lattice_deform_data_create(const Object *oblatt, const Object *ob) ATTR_WARN_UNUSED_RESULT
void BKE_lattice_deform_data_destroy(LatticeDeformData *lattice_deform_data)
void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data, float co[3], float weight)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
void BKE_id_free(Main *bmain, void *idv)
void id_us_plus(ID *id)
Definition lib_id.cc:351
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1482
void id_us_min(ID *id)
Definition lib_id.cc:359
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2560
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data_, func_call_)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_USER
@ IDWALK_CB_NOP
int BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:120
@ IDWALK_DO_DEPRECATED_POINTERS
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
void BKE_mesh_orco_verts_transform(Mesh *mesh, blender::MutableSpan< blender::float3 > orco, bool invert)
void BKE_mesh_texspace_ensure(Mesh *mesh)
BLI_INLINE int BKE_mesh_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i)
void BKE_mesh_tessface_ensure(Mesh *mesh)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
void BKE_modifier_free(ModifierData *md)
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md)
ModifierData * BKE_modifier_new(int type)
General operations, lookup, etc. for blender objects.
void BKE_object_modifier_set_active(Object *ob, ModifierData *md)
#define PSYS_FRAND_COUNT
void psys_thread_context_init(struct ParticleThreadContext *ctx, struct ParticleSimulationData *sim)
#define DMCACHE_NOTFOUND
void psys_tasks_free(struct ParticleTask *tasks, int numtasks)
#define LOOP_SHOWN_PARTICLES
void psys_unique_name(struct Object *object, struct ParticleSystem *psys, const char *defname) ATTR_NONNULL(1
void psys_apply_child_modifiers(struct ParticleThreadContext *ctx, struct ListBase *modifiers, struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], float hairmat[4][4], struct ParticleCacheKey *keys, struct ParticleCacheKey *parent_keys, const float parent_orco[3])
void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int endpart, struct ParticleTask **r_tasks, int *r_numtasks)
void psys_thread_context_free(struct ParticleThreadContext *ctx)
#define LOOP_PARTICLES
#define DMCACHE_ISCHILD
#define PARTICLE_PSMD
#define PARTICLE_P
BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
#define PEP_EDIT_RECALC
void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys)
struct PointCache * BKE_ptcache_add(struct ListBase *ptcaches)
#define PTCACHE_CLEAR_ALL
void BKE_ptcache_blend_read_data(struct BlendDataReader *reader, struct ListBase *ptcaches, struct PointCache **ocache, int force_disk)
int BKE_ptcache_mem_index_find(struct PTCacheMem *pm, unsigned int index)
void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
void BKE_ptcache_make_particle_key(struct ParticleKey *key, int index, void **data, float time)
void BKE_ptcache_free_list(struct ListBase *ptcaches)
#define PEK_SELECT
void BKE_ptcache_blend_write(struct BlendWriter *writer, struct ListBase *ptcaches)
float BKE_scene_frame_to_ctime(const Scene *scene, int frame)
Definition scene.cc:2322
void BKE_texture_mtex_foreach_id(struct LibraryForeachIDData *data, struct MTex *mtex)
Definition texture.cc:230
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ATTR_FALLTHROUGH
void BLI_bvhtree_free(BVHTree *tree)
A KD-tree for nearest neighbor search.
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
MINLINE int max_ii(int a, int b)
#define M_PI
MINLINE float safe_acosf(float a)
int isect_point_quad_v2(const float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition math_geom.cc:56
void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3], const float x2[3], const float v2[3], float t)
int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:39
void interp_weights_poly_v3(float w[], float v[][3], int n, const float co[3])
bool map_to_sphere(float *r_u, float *r_v, float x, float y, float z)
void mul_m3_v3(const float M[3][3], float r[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void unit_m4(float m[4][4])
Definition rct.c:1127
void mul_m4_v3(const float M[4][4], float r[3])
void transpose_m3_m4(float R[3][3], const float M[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void transpose_m4(float R[4][4])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void quat_to_mat4(float m[4][4], const float q[4])
void mul_qt_v3(const float q[4], float r[3])
void unit_qt(float q[4])
void mat3_to_quat_legacy(float q[4], const float wmat[3][3])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
#define RAD2DEGF(_rad)
void copy_qt_qt(float q[4], const float a[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v4_v4v4(float r[4], const float a[4], const float b[4], float t)
Definition math_vector.c:45
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition math_vector.c:36
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
void interp_v3_v3v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float w[4])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Random number functions.
void int BLI_rng_get_int(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:78
struct RNG * BLI_rng_new(unsigned int seed)
Definition rand.cc:39
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:58
struct RNG * BLI_rng_new_srandom(unsigned int seed)
Definition rand.cc:46
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:93
#define STRNCPY(dst, src)
Definition BLI_string.h:593
unsigned int uint
@ TASK_PRIORITY_HIGH
Definition BLI_task.h:57
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition task_pool.cc:471
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
Definition task_pool.cc:394
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:230
void BLI_task_pool_free(TaskPool *pool)
Definition task_pool.cc:431
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition task_pool.cc:450
#define CLAMP(a, b, c)
#define POINTER_AS_INT(i)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define BLT_I18NCONTEXT_ID_PARTICLESETTINGS
#define DATA_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ DAG_EVAL_RENDER
void DEG_relations_tag_update(Main *bmain)
float DEG_get_ctime(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
#define FILTER_ID_OB
Definition DNA_ID.h:1181
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
#define FILTER_ID_GR
Definition DNA_ID.h:1170
#define FILTER_ID_TE
Definition DNA_ID.h:1187
#define FILTER_ID_PA
Definition DNA_ID.h:1191
@ INDEX_ID_PA
Definition DNA_ID.h:1286
@ ID_PA
@ eBoidRuleType_Goal
@ eBoidRuleType_Fight
@ eBoidRuleType_Avoid
@ eBoidRuleType_FollowLeader
@ eBoidRuleType_AvoidCollision
@ eBoidRuleType_AverageSpeed
Object groups, one object can be in many groups at once.
@ CU_PATH_RADIUS
#define CD_MASK_ORIGINDEX
#define CD_MASK_ORCO
#define CD_MASK_MDEFORMVERT
#define CD_MASK_MTFACE
#define CD_MASK_ORIGSPACE_MLOOP
#define DNA_struct_default_get(struct_name)
@ SNDPARTICLE_COMBINED_EXPORT_OFF
@ KEY_CARDINAL
@ KEY_BSPLINE
@ TEXCO_ORCO
@ TEXCO_PARTICLE
@ TEXCO_GLOB
@ TEXCO_OBJECT
@ eModifierMode_Render
@ eModifierMode_Realtime
@ MOD_FLUID_TYPE_DOMAIN
@ MOD_FLUID_TYPE_FLOW
@ eModifierType_ParticleSystem
@ eModifierType_Lattice
@ eModifierType_Fluid
@ eModifierType_DynamicPaint
@ OB_MODE_PARTICLE_EDIT
@ PFIELD_GUIDE_PATH_ADD
@ PFIELD_GUIDE_PATH_WEIGHT
@ OB_MESH
@ PART_DRAW_COL_MAT
@ PART_FROM_VOLUME
@ PART_FROM_VERT
@ PART_FROM_FACE
@ PART_DUPLIW_CURRENT
@ PART_UNBORN
@ PART_CHILD_LONG_HAIR
@ PART_CHILD_GUIDE
@ PART_CHILD_EFFECT
@ PART_HAIR_BSPLINE
@ PART_DIED
@ PART_DRAW_GR
@ PART_DRAW_OB
@ PART_FLUID_FLIP
@ PART_FLUID_BUBBLE
@ PART_FLUID_SPRAYBUBBLE
@ PART_FLUID_TRACER
@ PART_FLUID_FOAM
@ PART_FLUID_SPRAYFOAMBUBBLE
@ PART_FLUID_SPRAYFOAM
@ PART_HAIR
@ PART_FLUID_SPRAY
@ PART_FLUID_FOAMBUBBLE
@ PARS_REKEY
@ PARS_UNEXIST
struct ParticleSettings ParticleSettings
@ PART_ABS_PATH_TIME
@ PSYS_VG_ROUGHE
@ PSYS_VG_LENGTH
@ PSYS_VG_ROUGH1
@ PSYS_VG_CLUMP
@ PSYS_VG_KINK
@ PSYS_VG_EFFECTOR
@ PSYS_VG_ROUGH2
@ PSYS_VG_TWIST
@ PAMAP_DENS
@ PAMAP_FIELD
@ PAMAP_CHILD
@ PAMAP_KINK_FREQ
@ PAMAP_TWIST
@ PAMAP_DAMP
@ PAMAP_SIZE
@ PAMAP_IVEL
@ PAMAP_GRAVITY
@ PAMAP_LIFE
@ PAMAP_KINK_AMP
@ PAMAP_TIME
@ PAMAP_CLUMP
@ PAMAP_LENGTH
@ PAMAP_ROUGH
@ PARS_DEAD
@ PARS_UNBORN
@ PART_CHILD_FACES
@ PART_KINK_SPIRAL
@ PART_ROT_VEL
@ PSYS_TOT_VG
@ PART_PHYS_FLUID
@ PART_PHYS_KEYED
@ PART_PHYS_BOIDS
@ PART_PHYS_NO
@ SPH_VISCOELASTIC_SPRINGS
@ PART_CHILD_USE_TWIST_CURVE
@ PART_CHILD_USE_CLUMP_CURVE
@ PART_CHILD_USE_CLUMP_NOISE
@ PART_CHILD_USE_ROUGH_CURVE
@ PSYS_CURRENT
@ PSYS_DISABLED
@ PSYS_HAIR_DYNAMICS
@ PSYS_EDITED
@ PSYS_DELETE
@ PSYS_HAIR_DONE
@ PSYS_GLOBAL_HAIR
@ PSYS_KEYED_TIMING
@ PSYS_SHARED_CACHES
@ PSYS_KEYED
@ PART_DISTR_GRID
@ PE_DRAW_PART
@ PHYS_GLOBAL_GRAVITY
@ PE_BRUSH_WEIGHT
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
#define MAX_MTEX
Definition Stroke.h:33
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
static unsigned long seed
Definition btSoftBody.h:39
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
constexpr const T * data() const
Definition BLI_span.hh:216
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
#define printf
double time
const Depsgraph * depsgraph
Lattice lattice
#define powf(x, y)
#define fabsf(x)
int len
TaskPool * task_pool
KDTree_3d * tree
draw_view in_light_buf[] float
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
smooth(Type::FLOAT, "radius") .smooth(Type flat(Type::INT, "id")
#define rot(x, k)
blender::gpu::Batch * quad
uint col
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
static ulong state[N]
Frequency::GEOMETRY nor[]
void BKE_particle_batch_cache_dirty_tag(ParticleSystem *psys, int mode)
Definition particle.cc:5295
void BKE_particlesettings_clump_curve_init(ParticleSettings *part)
Definition particle.cc:4104
void BKE_particle_system_blend_read_after_liblink(BlendLibReader *, Object *ob, ID *, ListBase *particles)
Definition particle.cc:5441
static int psys_map_index_on_dm(Mesh *mesh, int from, int index, int index_dmcache, const float fw[4], float, int *mapindex, float mapfw[4])
Definition particle.cc:1944
static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *bufs)
Definition particle.cc:518
static void particle_settings_blend_read_after_liblink(BlendLibReader *, ID *id)
Definition particle.cc:372
ParticleSystem * psys_get_current(Object *ob)
Definition particle.cc:534
void BKE_particle_system_blend_read_data(BlendDataReader *reader, ListBase *particles)
Definition particle.cc:5353
void psys_mat_hair_to_object(Object *, Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
Definition particle.cc:3851
void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3])
Definition particle.cc:2241
void free_hair(Object *object, ParticleSystem *psys, int dynamics)
Definition particle.cc:843
void object_remove_particle_system(Main *bmain, Scene *, Object *ob, ParticleSystem *psys)
Definition particle.cc:3991
static void psys_w_to_origspace(const float w[4], float uv[2])
Definition particle.cc:1794
void psys_free_particles(ParticleSystem *psys)
Definition particle.cc:929
float psys_get_timestep(ParticleSimulationData *sim)
Definition particle.cc:4474
float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
Definition particle.cc:4478
static void particle_settings_blend_read_data(BlendDataReader *reader, ID *id)
Definition particle.cc:320
void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
Definition particle.cc:2277
#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue)
Definition particle.cc:4237
static void particle_settings_init(ID *id)
Definition particle.cc:90
ParticleSettings * BKE_particlesettings_add(Main *bmain, const char *name)
Definition particle.cc:4095
void BKE_particle_system_blend_write(BlendWriter *writer, ListBase *particles)
Definition particle.cc:5308
static ParticleCacheKey ** psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int totkeys)
Definition particle.cc:492
static int get_pointcache_times_for_particle(PointCache *cache, int index, float *r_start, float *r_dietime)
Definition particle.cc:1244
ParticleSystem * psys_eval_get(Depsgraph *depsgraph, Object *object, ParticleSystem *psys)
Definition particle.cc:664
void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, bool velocity)
Definition particle.cc:1137
static void psys_cache_edit_paths_iter(void *__restrict iter_data_v, const int iter, const TaskParallelTLS *__restrict)
Definition particle.cc:3496
void psys_sim_data_init(ParticleSimulationData *sim)
Definition particle.cc:588
void copy_particle_key(ParticleKey *to, ParticleKey *from, int time)
Definition particle.cc:3741
void psys_free(Object *ob, ParticleSystem *psys)
Definition particle.cc:975
void psys_interpolate_mcol(const MCol *mcol, int quad, const float w[4], MCol *mc)
Definition particle.cc:1745
float PSYS_FRAND_BASE[PSYS_FRAND_COUNT]
Definition particle.cc:413
void psys_interpolate_uvs(const MTFace *tface, int quad, const float w[4], float uvco[2])
Definition particle.cc:1722
void psys_enable_all(Object *ob)
Definition particle.cc:647
ModifierData * object_add_particle_system(Main *bmain, const Scene *scene, Object *ob, const char *name)
Definition particle.cc:3975
static float interpolate_particle_value(float v1, float v2, float v3, float v4, const float w[4], int four)
Definition particle.cc:1122
static int get_particle_uv(Mesh *mesh, ParticleData *pa, int index, const float fuv[4], char *name, float *texco, bool from_vert)
Definition particle.cc:4150
static void get_pointcache_keys_for_time(Object *, PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2)
Definition particle.cc:1193
static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind)
Definition particle.cc:1286
void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, const bool vel)
Definition particle.cc:4599
static PTCacheEdit * psys_orig_edit_get(ParticleSystem *psys)
Definition particle.cc:680
static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey)
Definition particle.cc:1335
void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
Definition particle.cc:4118
int psys_particle_dm_face_lookup(Mesh *mesh_final, Mesh *mesh_original, int findex_orig, const float fw[4], LinkNode **poly_nodes)
Definition particle.cc:1830
static void offset_child(ChildParticle *cpa, ParticleKey *par, float *par_rot, ParticleKey *child, float flat, float radius)
Definition particle.cc:2551
void psys_mat_hair_to_global(Object *ob, Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
Definition particle.cc:3907
void psys_emitter_customdata_mask(ParticleSystem *psys, CustomData_MeshMasks *r_cddata_masks)
Definition particle.cc:2202
void BKE_particle_init_rng()
Definition particle.cc:415
static void get_cpa_texture(Mesh *mesh, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra)
Definition particle.cc:4243
#define CLAMP_WARP_PARTICLE_TEXTURE_POS(type, pvalue)
Definition particle.cc:4228
void psys_free_children(ParticleSystem *psys)
Definition particle.cc:919
ParticleSystemModifierData * psys_get_modifier(Object *ob, ParticleSystem *psys)
Definition particle.cc:2150
static void psys_thread_create_path(ParticleTask *task, ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
Definition particle.cc:2792
bool psys_check_edited(ParticleSystem *psys)
Definition particle.cc:732
void BKE_particle_partdeflect_blend_read_data(BlendDataReader *, PartDeflect *)
Definition particle.cc:316
void psys_sim_data_free(ParticleSimulationData *sim)
Definition particle.cc:629
static ParticleCacheKey * pcache_key_segment_endpoint_safe(ParticleCacheKey *key)
Definition particle.cc:487
static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCacheKey *result)
Definition particle.cc:1558
ModifierData * object_copy_particle_system(Main *bmain, const Scene *scene, Object *ob, const ParticleSystem *psys_orig)
Definition particle.cc:3983
static float psys_interpolate_value_from_verts(Mesh *mesh, short from, int index, const float fw[4], const float *values)
Definition particle.cc:1771
void psys_check_group_weights(ParticleSettings *part)
Definition particle.cc:762
void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys)
Definition particle.cc:5253
void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, const bool editupdate, const bool use_render_params)
Definition particle.cc:3148
void psys_mat_hair_to_orco(Object *ob, Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
Definition particle.cc:3877
void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params)
Definition particle.cc:2601
void psys_free_path_cache(ParticleSystem *psys, PTCacheEdit *edit)
Definition particle.cc:904
static void hair_to_particle(ParticleKey *key, HairKey *hkey)
Definition particle.cc:1343
static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, ParticleInterpolationData *pind, ParticleKey *result)
Definition particle.cc:1355
void(* BKE_particle_batch_cache_free_cb)(ParticleSystem *psys)
Definition particle.cc:5293
float * psys_cache_vgroup(Mesh *mesh, ParticleSystem *psys, int vgroup)
Definition particle.cc:2575
static void triatomat(float *v1, float *v2, float *v3, const float(*uv)[2], float mat[4][4])
Definition particle.cc:3768
bool psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, const bool always)
Definition particle.cc:4886
static void particle_settings_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int)
Definition particle.cc:102
void(* BKE_particle_batch_cache_dirty_tag_cb)(ParticleSystem *psys, int mode)
Definition particle.cc:5292
static void exec_child_path_cache(TaskPool *__restrict, void *taskdata)
Definition particle.cc:3132
void psys_set_current_num(Object *ob, int index)
Definition particle.cc:567
void psys_free_pdd(ParticleSystem *psys)
Definition particle.cc:959
int psys_uses_gravity(ParticleSimulationData *sim)
Definition particle.cc:826
static void free_child_path_cache(ParticleSystem *psys)
Definition particle.cc:898
static void fluid_free_settings(SPHFluidSettings *fluid)
Definition particle.cc:836
void psys_copy_particles(ParticleSystem *psys_dst, ParticleSystem *psys_src)
Definition particle.cc:1053
static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4], float neww[4])
Definition particle.cc:1801
float psys_get_dietime_from_cache(PointCache *cache, int index)
Definition particle.cc:1271
static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCacheKey *key1, ParticleCacheKey *key2, float *prev_tangent, int i)
Definition particle.cc:3215
static void particle_settings_free_data(ID *id)
Definition particle.cc:141
void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float uv[2], float orco[3])
Definition particle.cc:5056
short psys_get_current_num(Object *ob)
Definition particle.cc:548
bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params)
Definition particle.cc:706
void psys_get_from_key(ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time)
Definition particle.cc:3752
#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue)
Definition particle.cc:4222
void psys_vec_rot_to_face(Mesh *mesh, ParticleData *pa, float vec[3])
Definition particle.cc:3898
static void particle_settings_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition particle.cc:259
void BKE_particle_batch_cache_free(ParticleSystem *psys)
Definition particle.cc:5301
void free_keyed_keys(ParticleSystem *psys)
Definition particle.cc:878
uint PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT]
Definition particle.cc:412
void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_render_params)
Definition particle.cc:3256
float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float, float *)
Definition particle.cc:4510
bool do_guides(Depsgraph *depsgraph, ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time)
Definition particle.cc:2332
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex)
Definition particle.cc:4538
void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[4][4], float *scale)
Definition particle.cc:5159
void psys_find_group_weights(ParticleSettings *part)
Definition particle.cc:741
uint PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]
Definition particle.cc:411
int count_particles_mod(ParticleSystem *psys, int totgr, int cur)
Definition particle.cc:464
void psys_interpolate_face(Mesh *mesh, const float(*vert_positions)[3], const float(*vert_normals)[3], const MFace *mface, MTFace *tface, const float(*orcodata)[3], float w[4], float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3])
Definition particle.cc:1594
#define PATH_CACHE_BUF_SIZE
Definition particle.cc:485
static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *, float effector, float, float, float *length, float *vec)
Definition particle.cc:2499
void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra)
Definition particle.cc:4338
IDTypeInfo IDType_ID_PA
Definition particle.cc:381
void psys_cache_edit_paths(Depsgraph *depsgraph, Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params)
Definition particle.cc:3662
float psys_particle_value_from_verts(Mesh *mesh, short from, ParticleData *pa, float *values)
Definition particle.cc:2136
static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ParticleSimulationData *sim, Scene *scene, float cfra, const bool editupdate, const bool use_render_params)
Definition particle.cc:2676
void psys_disable_all(Object *ob)
Definition particle.cc:639
static void write_boid_state(BlendWriter *writer, BoidState *state)
Definition particle.cc:224
static void mvert_to_particle(ParticleKey *key, float3 *position, HairKey *hkey)
Definition particle.cc:1349
void psys_particle_on_dm(Mesh *mesh_final, int from, int index, int index_dmcache, const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3])
Definition particle.cc:2017
static ModifierData * object_add_or_copy_particle_system(Main *bmain, const Scene *scene, Object *ob, const char *name, const ParticleSystem *psys_orig)
Definition particle.cc:3921
static void psys_face_mat(Object *ob, Mesh *mesh, ParticleData *pa, float mat[4][4], int orco)
Definition particle.cc:3810
ParticleSystem * psys_orig_get(ParticleSystem *psys)
Definition particle.cc:656
bool psys_in_edit_mode(Depsgraph *depsgraph, const ParticleSystem *psys)
Definition particle.cc:688
static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data)
Definition particle.cc:170
static void psys_particle_on_shape(int, int, float *, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3])
Definition particle.cc:2170
#define SET_PARTICLE_TEXTURE(type, pvalue, texfac)
Definition particle.cc:4216
int count_particles(ParticleSystem *psys)
Definition particle.cc:446
void BKE_particlesettings_twist_curve_init(ParticleSettings *part)
Definition particle.cc:4132
static void psys_task_init_path(ParticleTask *task, ParticleSimulationData *sim)
Definition particle.cc:2783
float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump, bool use_clump_noise, float clump_noise_size, const CurveMapping *clumpcurve)
void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat, short type, short axis, const float obmat[4][4], int smooth_start)
void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, float mat[4][4], ParticleKey *state, float t)
return ret
static const int steps
struct Object * object
struct Object * ground
struct Object * ob
struct Object * ob
struct ListBase states
ParticleSystemModifierData * psmd
Definition particle.cc:3490
struct ListBase ptcaches
struct ClothSolverResult * solver_result
struct ClothHairData * hairdata
struct Cloth * clothObject
struct PointCache * point_cache
struct ClothSimSettings * sim_parms
struct ClothCollSettings * coll_parms
struct EffectorWeights * effector_weights
CurveMapPoint * curve
CurveMap cm[4]
struct Object * taperobj
struct DynamicPaintBrushSettings * brush
float distance
Definition BKE_effect.h:59
float vec_to_point[3]
Definition BKE_effect.h:58
float nor[3]
Definition BKE_effect.h:55
struct Collection * group
struct ParticleSystem * psys
struct FluidDomainSettings * domain
struct FluidFlowSettings * flow
float world_co[3]
Definition DNA_ID.h:413
void * data
void * link
struct LinkNode * next
void * last
void * first
unsigned int v2
unsigned int v1
unsigned int v4
unsigned int v3
float uv[4][2]
short texco
float fieldfac
float roughfac
float kinkampfac
float lifefac
float padensfac
short blendtype
float kinkfac
float dampfac
float def_var
float clumpfac
float ivelfac
short mapto
struct Object * object
float timefac
float lengthfac
float gravityfac
char uvname[68]
float twistfac
float sizefac
struct Tex * tex
MeshRuntimeHandle * runtime
CustomData face_data
CustomData vert_data
CustomData fdata_legacy
int totface_legacy
struct ModifierData * next
ListBase particlesystem
short transflag
ListBase modifiers
ListBase pathcachebufs
struct ParticleCacheKey ** pathcache
PTCacheEditPoint * points
struct ParticleSystem * psys
struct ParticleSystemModifierData * psmd_eval
unsigned int frame
struct PTCacheMem * next
struct PTCacheMem * prev
struct Object * f_source
ParticleThreadContext * thread_ctx
ParticleSimulationData * sim
BoidParticle * boid
ParticleKey state
ParticleKey prev_state
ParticleKey * keys
struct ParticleDupliWeight * next
ParticleKey * kkey[2]
Definition particle.cc:1174
PTCacheEditKey * ekey[2]
Definition particle.cc:1180
PTCacheEditPoint * epoint
Definition particle.cc:1179
struct CurveMapping * clumpcurve
struct PartDeflect * pd2
struct Collection * collision_group
struct Collection * instance_collection
struct Object * bb_ob
struct CurveMapping * roughcurve
struct CurveMapping * twistcurve
struct BoidSettings * boids
struct EffectorWeights * effector_weights
struct MTex * mtex[18]
struct PartDeflect * pd
struct ListBase instance_weights
struct Object * instance_object
struct SPHFluidSettings * fluid
struct Depsgraph * depsgraph
struct ParticleSystemModifierData * psmd
struct Scene * scene
struct ParticleSystem * psys
struct Object * ob
struct ListBase * colliders
struct ParticleSystem * psys
ParticleSpring * fluid_springs
ChildParticle * child
struct PTCacheEdit * edit
struct ListBase ptcaches
ParticleData * particles
struct ListBase targets
ParticleSettings * part
struct ListBase * effectors
struct ParticleSystem * next
struct PointCache * pointcache
struct BVHTree * bvhtree
struct ClothModifierData * clmd
struct LatticeDeformData * lattice_deform_data
struct ParticleCacheKey ** childcache
struct Mesh * hair_in_mesh
struct KDTree_3d * tree
struct ParticleSystem * orig_psys
struct Mesh * hair_out_mesh
struct ParticleDrawData * pdd
struct ParticleCacheKey ** pathcache
void(* free_edit)(struct PTCacheEdit *edit)
struct ParticleTarget * prev
struct ParticleTarget * next
struct CurveMapping * roughcurve
struct Material * ma
struct CurveMapping * twistcurve
struct CurveMapping * clumpcurve
struct ParticleSimulationData sim
struct ListBase mem_cache
struct PTCacheEdit * edit
Definition rand.cc:33
struct PhysicsSettings physics_settings
struct ToolSettings * toolsettings
struct RenderData r
struct ParticleEditSettings particle
bool RE_texture_evaluate(const MTex *mtex, const float vec[3], const int thread, ImagePool *pool, const bool skip_load_image, const bool texnode_preview, float *r_intensity, float r_rgba[4])
float texture_value_blend(float tex, float out, float fact, float facg, int blendtype)
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:138