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