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