Blender V5.0
effect.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cmath>
11#include <cstdarg>
12#include <cstddef>
13#include <cstdlib>
14
15#include "MEM_guardedalloc.h"
16
17#include "DNA_curve_types.h"
18#include "DNA_listBase.h"
19#include "DNA_mesh_types.h"
21#include "DNA_object_types.h"
22#include "DNA_particle_types.h"
23#include "DNA_scene_types.h"
24#include "DNA_texture_types.h"
25
26#include "BLI_ghash.h"
27#include "BLI_listbase.h"
28#include "BLI_math_base_safe.h"
29#include "BLI_math_matrix.h"
30#include "BLI_math_rotation.h"
31#include "BLI_math_vector.h"
32#include "BLI_noise.h"
33#include "BLI_rand.h"
34#include "BLI_string.h"
35#include "BLI_time.h"
36#include "BLI_utildefines.h"
37
38#include "BKE_anim_path.h" /* needed for where_on_path */
39#include "BKE_bvhutils.hh"
40#include "BKE_collection.hh"
41#include "BKE_collision.h"
42#include "BKE_curve.hh"
43#include "BKE_displist.h"
44#include "BKE_effect.h"
45#include "BKE_fluid.h"
46#include "BKE_global.hh"
47#include "BKE_modifier.hh"
48#include "BKE_object.hh"
49#include "BKE_object_types.hh"
50#include "BKE_particle.h"
51
52#include "DEG_depsgraph.hh"
55
56#include "RE_texture.h"
57
59{
60 EffectorWeights *weights = MEM_callocN<EffectorWeights>("EffectorWeights");
61 for (int i = 0; i < NUM_PFIELD_TYPES; i++) {
62 weights->weight[i] = 1.0f;
63 }
64
65 weights->global_gravity = 1.0f;
66
67 weights->group = collection;
68
69 return weights;
70}
72{
73 PartDeflect *pd;
74
75 pd = MEM_callocN<PartDeflect>("PartDeflect");
76
77 pd->forcefield = type;
78 pd->pdef_sbdamp = 0.1f;
79 pd->pdef_sbift = 0.2f;
80 pd->pdef_sboft = 0.02f;
81 pd->pdef_cfrict = 5.0f;
82 pd->seed = (uint(ceil(BLI_time_now_seconds())) + 1) % 128;
83 pd->f_strength = 1.0f;
84 pd->f_damp = 1.0f;
85
86 /* set sensible defaults based on type */
87 switch (type) {
88 case PFIELD_VORTEX:
90 break;
91 case PFIELD_WIND:
93 pd->f_flow = 1.0f; /* realistic wind behavior */
94 pd->f_wind_factor = 1.0f; /* only act perpendicularly to a surface */
95 break;
96 case PFIELD_TEXTURE:
97 pd->f_size = 1.0f;
98 break;
100 pd->f_flow = 1.0f;
101 break;
102 }
104
105 return pd;
106}
107
108/************************ PARTICLES ***************************/
109
111{
112 if (pd_src == nullptr) {
113 return nullptr;
114 }
115 PartDeflect *pd_dst = static_cast<PartDeflect *>(MEM_dupallocN(pd_src));
116 return pd_dst;
117}
118
120{
121 if (!pd) {
122 return;
123 }
124 MEM_freeN(pd);
125}
126
127/******************** EFFECTOR RELATIONS ***********************/
128
129static void precalculate_effector(Depsgraph *depsgraph, EffectorCache *eff)
130{
131 float ctime = DEG_get_ctime(depsgraph);
132 uint cfra = uint(ctime >= 0 ? ctime : -ctime);
133
134 eff->rng = BLI_rng_new(eff->pd->seed + cfra);
135
136 if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type == OB_CURVES_LEGACY) {
137 Curve *cu = static_cast<Curve *>(eff->ob->data);
138 if (cu->flag & CU_PATH) {
139 if (eff->ob->runtime->curve_cache == nullptr ||
140 eff->ob->runtime->curve_cache->anim_path_accum_length == nullptr)
141 {
143 }
144
145 if (eff->ob->runtime->curve_cache->anim_path_accum_length) {
147 eff->ob, 0.0, eff->guide_loc, eff->guide_dir, nullptr, &eff->guide_radius, nullptr);
148 mul_m4_v3(eff->ob->object_to_world().ptr(), eff->guide_loc);
149 mul_mat3_m4_v3(eff->ob->object_to_world().ptr(), eff->guide_dir);
150 }
151 }
152 }
153 else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) {
155 if (eff->ob->type == OB_CURVES_LEGACY) {
156 eff->flag |= PE_USE_NORMAL_DATA;
157 }
158 }
159 else if (eff->psys) {
160 psys_update_particle_tree(eff->psys, ctime);
161 }
162}
163
164static void add_effector_relation(ListBase *relations,
165 Object *ob,
166 ParticleSystem *psys,
167 PartDeflect *pd)
168{
169 EffectorRelation *relation = MEM_callocN<EffectorRelation>("EffectorRelation");
170 relation->ob = ob;
171 relation->psys = psys;
172 relation->pd = pd;
173
174 BLI_addtail(relations, relation);
175}
176
177static void add_effector_evaluation(ListBase **effectors,
178 Depsgraph *depsgraph,
179 Scene *scene,
180 Object *ob,
181 ParticleSystem *psys,
182 PartDeflect *pd)
183{
184 if (*effectors == nullptr) {
185 *effectors = MEM_callocN<ListBase>("effector effectors");
186 }
187
188 EffectorCache *eff = MEM_callocN<EffectorCache>("EffectorCache");
189 eff->depsgraph = depsgraph;
190 eff->scene = scene;
191 eff->ob = ob;
192 eff->psys = psys;
193 eff->pd = pd;
194 eff->frame = -1;
195 BLI_addtail(*effectors, eff);
196
198}
199
201 const Scene *scene,
202 ViewLayer *view_layer,
203 Collection *collection)
204{
205 Base *base = BKE_collection_or_layer_objects(scene, view_layer, collection);
206 const bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
207 const int base_flag = (for_render) ? BASE_ENABLED_RENDER : BASE_ENABLED_VIEWPORT;
208
209 ListBase *relations = MEM_callocN<ListBase>("effector relations");
210
211 for (; base; base = base->next) {
212 if (!(base->flag & base_flag)) {
213 continue;
214 }
215
216 Object *ob = base->object;
217
218 if (ob->pd && ob->pd->forcefield) {
219 add_effector_relation(relations, ob, nullptr, ob->pd);
220 }
221
223 ParticleSettings *part = psys->part;
224
225 if (psys_check_enabled(ob, psys, for_render)) {
226 if (part->pd && part->pd->forcefield) {
227 add_effector_relation(relations, ob, psys, part->pd);
228 }
229 if (part->pd2 && part->pd2->forcefield) {
230 add_effector_relation(relations, ob, psys, part->pd2);
231 }
232 }
233 }
234 }
235
236 return relations;
237}
238
240{
241 if (lb) {
242 BLI_freelistN(lb);
243 MEM_freeN(lb);
244 }
245}
246
247/* Check that the force field isn't disabled via its flags. */
248static bool is_effector_enabled(PartDeflect *pd, bool use_rotation)
249{
250 switch (pd->forcefield) {
251 case PFIELD_BOID:
252 case PFIELD_GUIDE:
253 return true;
254
255 case PFIELD_TEXTURE:
256 return (pd->flag & PFIELD_DO_LOCATION) != 0 && pd->tex != nullptr;
257
258 default:
259 if (use_rotation) {
260 return (pd->flag & (PFIELD_DO_LOCATION | PFIELD_DO_ROTATION)) != 0;
261 }
262 else {
263 return (pd->flag & PFIELD_DO_LOCATION) != 0;
264 }
265 }
266}
267
268/* Check that the force field won't have zero effect due to strength settings. */
270{
271 if (pd->f_strength != 0.0f) {
272 return true;
273 }
274
275 if (pd->forcefield == PFIELD_TEXTURE) {
276 return false;
277 }
278
279 if (pd->f_noise > 0.0f || pd->f_flow != 0.0f) {
280 return true;
281 }
282
283 switch (pd->forcefield) {
284 case PFIELD_BOID:
285 case PFIELD_GUIDE:
286 return true;
287
288 case PFIELD_VORTEX:
289 return pd->shape != PFIELD_SHAPE_POINT;
290
291 case PFIELD_DRAG:
292 return pd->f_damp != 0.0f;
293
294 default:
295 return false;
296 }
297}
298
299/* Check if the force field will affect its user. */
300static bool is_effector_relevant(PartDeflect *pd, EffectorWeights *weights, bool use_rotation)
301{
302 return (weights->weight[pd->forcefield] != 0.0f) && is_effector_enabled(pd, use_rotation) &&
304}
305
307 Object *ob_src,
308 ParticleSystem *psys_src,
309 EffectorWeights *weights,
310 bool use_rotation)
311{
313 ListBase *relations = DEG_get_effector_relations(depsgraph, weights->group);
314 ListBase *effectors = nullptr;
315
316 if (!relations) {
317 return nullptr;
318 }
319
320 LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
321 /* Get evaluated object. */
322 Object *ob = DEG_get_evaluated(depsgraph, relation->ob);
323
324 if (relation->psys) {
325 /* Get evaluated particle system. */
326 ParticleSystem *psys = static_cast<ParticleSystem *>(BLI_findstring(
327 &ob->particlesystem, relation->psys->name, offsetof(ParticleSystem, name)));
328 ParticleSettings *part = psys->part;
329
330 if (psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0) {
331 continue;
332 }
333
334 PartDeflect *pd = (relation->pd == relation->psys->part->pd) ? part->pd : part->pd2;
335
336 if (!is_effector_relevant(pd, weights, use_rotation)) {
337 continue;
338 }
339
340 add_effector_evaluation(&effectors, depsgraph, scene, ob, psys, pd);
341 }
342 else {
343 /* Object effector. */
344 if (ob == ob_src) {
345 continue;
346 }
347 if (!is_effector_relevant(ob->pd, weights, use_rotation)) {
348 continue;
349 }
350 if (ob->pd->shape == PFIELD_SHAPE_POINTS && BKE_object_get_evaluated_mesh(ob) == nullptr) {
351 continue;
352 }
353
354 add_effector_evaluation(&effectors, depsgraph, scene, ob, nullptr, ob->pd);
355 }
356 }
357
358 return effectors;
359}
360
362{
363 if (lb) {
364 LISTBASE_FOREACH (EffectorCache *, eff, lb) {
365 if (eff->rng) {
366 BLI_rng_free(eff->rng);
367 }
368 if (eff->guide_data) {
369 MEM_freeN(eff->guide_data);
370 }
371 }
372
373 BLI_freelistN(lb);
374 MEM_freeN(lb);
375 }
376}
377
379 ParticleData *pa,
381 EffectedPoint *point)
382{
383 ParticleSettings *part = sim->psys->part;
384 point->loc = state->co;
385 point->vel = state->vel;
386 point->index = pa - sim->psys->particles;
387 point->size = pa->size;
388 point->charge = 0.0f;
389
390 if (part->pd && part->pd->forcefield == PFIELD_CHARGE) {
391 point->charge += part->pd->f_strength;
392 }
393
394 if (part->pd2 && part->pd2->forcefield == PFIELD_CHARGE) {
395 point->charge += part->pd2->f_strength;
396 }
397
398 point->vel_to_sec = 1.0f;
399 point->vel_to_frame = psys_get_timestep(sim);
400
401 point->flag = 0;
402
403 if (sim->psys->part->flag & PART_ROT_DYN) {
404 point->ave = state->ave;
405 point->rot = state->rot;
406 }
407 else {
408 point->ave = point->rot = nullptr;
409 }
410
411 point->psys = sim->psys;
412}
413
414void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
415{
416 point->loc = loc;
417 point->vel = vel;
418 point->index = index;
419 point->size = 0.0f;
420
421 point->vel_to_sec = float(scene->r.frs_sec);
422 point->vel_to_frame = 1.0f;
423
424 point->flag = 0;
425
426 point->ave = point->rot = nullptr;
427 point->psys = nullptr;
428}
429void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
430{
431 point->loc = loc;
432 point->vel = vel;
433 point->index = index;
434 point->size = 0.0f;
435
436 point->vel_to_sec = float(scene->r.frs_sec);
437 point->vel_to_frame = 1.0f;
438
439 point->flag = PE_WIND_AS_SPEED;
440
441 point->ave = point->rot = nullptr;
442
443 point->psys = nullptr;
444}
445/************************************************/
446/* Effectors */
447/************************************************/
448
449// triangle - ray callback function
450static void eff_tri_ray_hit(void * /*user_data*/,
451 int /*index*/,
452 const BVHTreeRay * /*ray*/,
453 BVHTreeRayHit *hit)
454{
455 /* whenever we hit a bounding box, we don't check further */
456 hit->dist = -1;
457 hit->index = 1;
458}
459
463static float eff_calc_visibility(ListBase *colliders,
464 EffectorCache *eff,
465 EffectorData *efd,
466 EffectedPoint *point)
467{
468 const int raycast_flag = BVH_RAYCAST_DEFAULT & ~BVH_RAYCAST_WATERTIGHT;
469 ListBase *colls = colliders;
470 float norm[3], len = 0.0;
471 float visibility = 1.0, absorption = 0.0;
472
473 if (!(eff->pd->flag & PFIELD_VISIBILITY)) {
474 return visibility;
475 }
476 if (!colls) {
477 colls = BKE_collider_cache_create(eff->depsgraph, eff->ob, nullptr);
478 }
479 if (!colls) {
480 return visibility;
481 }
482
485
486 /* check all collision objects */
488 CollisionModifierData *collmd = col->collmd;
489
490 if (col->ob == eff->ob) {
491 continue;
492 }
493 if (collmd->bvhtree) {
494 BVHTreeRayHit hit;
495
496 hit.index = -1;
497 hit.dist = len + FLT_EPSILON;
498
499 /* check if the way is blocked */
501 point->loc,
502 norm,
503 0.0f,
504 &hit,
506 nullptr,
507 raycast_flag) != -1)
508 {
509 absorption = col->ob->pd->absorption;
510
511 /* visibility is only between 0 and 1, calculated from 1-absorption */
512 visibility *= std::clamp(1.0f - absorption, 0.0f, 1.0f);
513
514 if (visibility <= 0.0f) {
515 break;
516 }
517 }
518 }
519 }
520
521 if (!colliders) {
523 }
524
525 return visibility;
526}
527
528/* Noise function for wind e.g. */
529static float wind_func(RNG *rng, float strength)
530{
531 int random = (BLI_rng_get_int(rng) + 1) % 128; /* max 2357 */
532 float force = BLI_rng_get_float(rng) + 1.0f;
533 float ret;
534 float sign = 0;
535
536 /* Dividing by 2 is not giving equal sign distribution. */
537 sign = (float(random) > 64.0f) ? 1.0f : -1.0f;
538
539 ret = sign * (float(random) / force) * strength / 128.0f;
540
541 return ret;
542}
543
544/* maxdist: zero effect from this distance outwards (if usemax) */
545/* mindist: full effect up to this distance (if usemin) */
546/* power: falloff with formula 1/r^power */
547static float falloff_func(
548 float fac, int usemin, float mindist, int usemax, float maxdist, float power)
549{
550 /* first quick checks */
551 if (usemax && fac > maxdist) {
552 return 0.0f;
553 }
554
555 if (usemin && fac < mindist) {
556 return 1.0f;
557 }
558
559 if (!usemin) {
560 mindist = 0.0;
561 }
562
563 return pow(double(1.0f + fac - mindist), double(-power));
564}
565
566static float falloff_func_dist(PartDeflect *pd, float fac)
567{
568 return falloff_func(fac,
569 pd->flag & PFIELD_USEMIN,
570 pd->mindist,
571 pd->flag & PFIELD_USEMAX,
572 pd->maxdist,
573 pd->f_power);
574}
575
576static float falloff_func_rad(PartDeflect *pd, float fac)
577{
578 return falloff_func(fac,
579 pd->flag & PFIELD_USEMINR,
580 pd->minrad,
581 pd->flag & PFIELD_USEMAXR,
582 pd->maxrad,
583 pd->f_power_r);
584}
585
587 EffectorData *efd,
588 EffectedPoint * /*point*/,
589 EffectorWeights *weights)
590{
591 float temp[3];
592 float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f;
593 float fac, r_fac;
594
595 fac = dot_v3v3(efd->nor, efd->vec_to_point2);
596
597 if (eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f) {
598 falloff = 0.0f;
599 }
600 else if (eff->pd->zdir == PFIELD_Z_NEG && fac > 0.0f) {
601 falloff = 0.0f;
602 }
603 else {
604 switch (eff->pd->falloff) {
606 falloff *= falloff_func_dist(eff->pd, efd->distance);
607 break;
608
609 case PFIELD_FALL_TUBE:
610 falloff *= falloff_func_dist(eff->pd, fabsf(fac));
611 if (falloff == 0.0f) {
612 break;
613 }
614
615 madd_v3_v3v3fl(temp, efd->vec_to_point2, efd->nor, -fac);
616 r_fac = len_v3(temp);
617 falloff *= falloff_func_rad(eff->pd, r_fac);
618 break;
619 case PFIELD_FALL_CONE:
620 falloff *= falloff_func_dist(eff->pd, fabsf(fac));
621 if (falloff == 0.0f) {
622 break;
623 }
624
625 r_fac = RAD2DEGF(safe_acosf(fac / len_v3(efd->vec_to_point2)));
626 falloff *= falloff_func_rad(eff->pd, r_fac);
627
628 break;
629 }
630 }
631
632 return falloff;
633}
634
636 const float co[3],
637 float surface_co[3],
638 float surface_nor[3],
639 float surface_vel[3])
640{
642 BVHTreeNearest nearest;
643
644 nearest.index = -1;
645 nearest.dist_sq = FLT_MAX;
646
647 BLI_bvhtree_find_nearest(bvhtree->tree, co, &nearest, bvhtree->nearest_callback, bvhtree);
648
649 if (nearest.index != -1) {
650 copy_v3_v3(surface_co, nearest.co);
651
652 if (surface_nor) {
653 copy_v3_v3(surface_nor, nearest.no);
654 }
655
656 if (surface_vel) {
657 const int *corner_verts = bvhtree->corner_verts.data();
658 const blender::int3 &tri = bvhtree->corner_tris[nearest.index];
659
660 copy_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[tri[0]]]);
661 add_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[tri[1]]]);
662 add_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[tri[2]]]);
663
664 mul_v3_fl(surface_vel, (1.0f / 3.0f));
665 }
666 return true;
667 }
668
669 return false;
670}
672 EffectorData *efd,
673 EffectedPoint *point,
674 int real_velocity)
675{
676 float cfra = DEG_get_ctime(eff->depsgraph);
677 bool ret = false;
678
679 /* In case surface object is in Edit mode when loading the .blend,
680 * surface modifier is never executed and bvhtree never built, see #48415. */
681 if (eff->pd && eff->pd->shape == PFIELD_SHAPE_SURFACE && eff->surmd &&
682 eff->surmd->runtime.bvhtree)
683 {
684 /* closest point in the object surface is an effector */
685 float vec[3];
686
687 /* using velocity corrected location allows for easier sliding over effector surface */
688 copy_v3_v3(vec, point->vel);
689 mul_v3_fl(vec, point->vel_to_frame);
690 add_v3_v3(vec, point->loc);
691
693 eff->surmd, vec, efd->loc, efd->nor, real_velocity ? efd->vel : nullptr);
694
695 efd->size = 0.0f;
696 }
697 else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) {
698 /* TODO: hair and points object support */
699 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(eff->ob);
700 if (mesh_eval != nullptr) {
701 const blender::Span<blender::float3> positions = mesh_eval->vert_positions();
702 const blender::Span<blender::float3> vert_normals = mesh_eval->vert_normals();
703 copy_v3_v3(efd->loc, positions[*efd->index]);
704 copy_v3_v3(efd->nor, vert_normals[*efd->index]);
705
706 mul_m4_v3(eff->ob->object_to_world().ptr(), efd->loc);
707 mul_mat3_m4_v3(eff->ob->object_to_world().ptr(), efd->nor);
708
709 normalize_v3(efd->nor);
710
711 efd->size = 0.0f;
712
713 ret = true;
714 }
715 }
716 else if (eff->psys) {
717 ParticleData *pa = eff->psys->particles + *efd->index;
719
720 /* exclude the particle itself for self effecting particles */
721 if (eff->psys == point->psys && *efd->index == point->index) {
722 /* pass */
723 }
724 else {
725 ParticleSimulationData sim = {nullptr};
726 sim.depsgraph = eff->depsgraph;
727 sim.scene = eff->scene;
728 sim.ob = eff->ob;
729 sim.psys = eff->psys;
730
731 /* TODO: time from actual previous calculated frame (step might not be 1) */
732 state.time = cfra - 1.0f;
733 ret = psys_get_particle_state(&sim, *efd->index, &state, false);
734
735 /* TODO */
736 // if (eff->pd->forcefiled == PFIELD_HARMONIC && ret==0) {
737 // if (pa->dietime < eff->psys->cfra)
738 // eff->flag |= PE_VELOCITY_TO_IMPULSE;
739 //}
740
741 copy_v3_v3(efd->loc, state.co);
742
743 /* rather than use the velocity use rotated x-axis (defaults to velocity) */
744 efd->nor[0] = 1.0f;
745 efd->nor[1] = efd->nor[2] = 0.0f;
746 mul_qt_v3(state.rot, efd->nor);
747
748 if (real_velocity) {
749 copy_v3_v3(efd->vel, state.vel);
750 }
751 efd->size = pa->size;
752 }
753 }
754 else {
755 /* use center of object for distance calculus */
756 const Object *ob = eff->ob;
757
758 /* Use z-axis as normal. */
759 normalize_v3_v3(efd->nor, ob->object_to_world().ptr()[2]);
760
761 if (eff->pd && ELEM(eff->pd->shape, PFIELD_SHAPE_PLANE, PFIELD_SHAPE_LINE)) {
762 float temp[3], translate[3];
763 sub_v3_v3v3(temp, point->loc, ob->object_to_world().location());
764 project_v3_v3v3(translate, temp, efd->nor);
765
766 /* for vortex the shape chooses between old / new force */
767 if (eff->pd->forcefield == PFIELD_VORTEX || eff->pd->shape == PFIELD_SHAPE_LINE) {
768 add_v3_v3v3(efd->loc, ob->object_to_world().location(), translate);
769 }
770 else { /* Normally `efd->loc` is closest point on effector XY-plane. */
771 sub_v3_v3v3(efd->loc, point->loc, translate);
772 }
773 }
774 else {
775 copy_v3_v3(efd->loc, ob->object_to_world().location());
776 }
777
778 zero_v3(efd->vel);
779 efd->size = 0.0f;
780
781 ret = true;
782 }
783
784 if (ret) {
785 sub_v3_v3v3(efd->vec_to_point, point->loc, efd->loc);
786 efd->distance = len_v3(efd->vec_to_point);
787
788 /* Rest length for harmonic effector,
789 * will have to see later if this could be extended to other effectors. */
790 if (eff->pd && eff->pd->forcefield == PFIELD_HARMONIC && eff->pd->f_size) {
791 mul_v3_fl(efd->vec_to_point, (efd->distance - eff->pd->f_size) / efd->distance);
792 }
793
794 if (eff->flag & PE_USE_NORMAL_DATA) {
796 copy_v3_v3(efd->nor2, efd->nor);
797 }
798 else {
799 /* for some effectors we need the object center every time */
800 sub_v3_v3v3(efd->vec_to_point2, point->loc, eff->ob->object_to_world().location());
801 normalize_v3_v3(efd->nor2, eff->ob->object_to_world().ptr()[2]);
802 }
803 }
804
805 return ret;
806}
808 EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p, int *step)
809{
810 *p = 0;
811 efd->index = p;
812
813 if (eff->pd->shape == PFIELD_SHAPE_POINTS) {
814 /* TODO: hair and points object support */
815 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(eff->ob);
816 *tot = mesh_eval != nullptr ? mesh_eval->verts_num : 1;
817
818 if (*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) {
819 *p = point->index % *tot;
820 *tot = *p + 1;
821 }
822 }
823 else if (eff->psys) {
824 *tot = eff->psys->totpart;
825
826 if (eff->pd->forcefield == PFIELD_CHARGE) {
827 /* Only the charge of the effected particle is used for
828 * interaction, not fall-offs. If the fall-offs aren't the
829 * same this will be nonphysical, but for animation this
830 * could be the wanted behavior. If you want physical
831 * correctness the fall-off should be spherical 2.0 anyways.
832 */
833 efd->charge = eff->pd->f_strength;
834 }
835 else if (eff->pd->forcefield == PFIELD_HARMONIC &&
836 (eff->pd->flag & PFIELD_MULTIPLE_SPRINGS) == 0)
837 {
838 /* every particle is mapped to only one harmonic effector particle */
839 *p = point->index % eff->psys->totpart;
840 *tot = *p + 1;
841 }
842
843 if (eff->psys->part->effector_amount) {
844 int totpart = eff->psys->totpart;
845 int amount = eff->psys->part->effector_amount;
846
847 *step = (totpart > amount) ? int(ceil(float(totpart) / float(amount))) : 1;
848 }
849 }
850 else {
851 *tot = 1;
852 }
853}
855 EffectorData *efd,
856 EffectedPoint *point,
857 float *total_force)
858{
859 TexResult result[4];
860 float tex_co[3], strength, force[3];
861 float nabla = eff->pd->tex_nabla;
862 int hasrgb;
863 short mode = eff->pd->tex_mode;
864
865 if (!eff->pd->tex) {
866 return;
867 }
868
869 strength = eff->pd->f_strength * efd->falloff;
870
871 copy_v3_v3(tex_co, point->loc);
872
873 if (eff->pd->flag & PFIELD_TEX_OBJECT) {
874 mul_m4_v3(eff->ob->world_to_object().ptr(), tex_co);
875
876 if (eff->pd->flag & PFIELD_TEX_2D) {
877 tex_co[2] = 0.0f;
878 }
879 }
880 else if (eff->pd->flag & PFIELD_TEX_2D) {
881 float fac = -dot_v3v3(tex_co, efd->nor);
882 madd_v3_v3fl(tex_co, efd->nor, fac);
883 }
884
885 hasrgb = multitex_ext(eff->pd->tex, tex_co, result, 0, nullptr, true, false);
886
887 if (hasrgb && mode == PFIELD_TEX_RGB) {
888 force[0] = (0.5f - result->trgba[0]) * strength;
889 force[1] = (0.5f - result->trgba[1]) * strength;
890 force[2] = (0.5f - result->trgba[2]) * strength;
891 }
892 else if (nabla != 0) {
893 strength /= nabla;
894
895 tex_co[0] += nabla;
896 multitex_ext(eff->pd->tex, tex_co, result + 1, 0, nullptr, true, false);
897
898 tex_co[0] -= nabla;
899 tex_co[1] += nabla;
900 multitex_ext(eff->pd->tex, tex_co, result + 2, 0, nullptr, true, false);
901
902 tex_co[1] -= nabla;
903 tex_co[2] += nabla;
904 multitex_ext(eff->pd->tex, tex_co, result + 3, 0, nullptr, true, false);
905
906 if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */
907 /* generate intensity if texture only has rgb value */
908 if (hasrgb & TEX_RGB) {
909 for (int i = 0; i < 4; i++) {
910 result[i].tin = (1.0f / 3.0f) *
911 (result[i].trgba[0] + result[i].trgba[1] + result[i].trgba[2]);
912 }
913 }
914 force[0] = (result[0].tin - result[1].tin) * strength;
915 force[1] = (result[0].tin - result[2].tin) * strength;
916 force[2] = (result[0].tin - result[3].tin) * strength;
917 }
918 else { /*PFIELD_TEX_CURL*/
919 float dbdy, dgdz, drdz, dbdx, dgdx, drdy;
920
921 dbdy = result[2].trgba[2] - result[0].trgba[2];
922 dgdz = result[3].trgba[1] - result[0].trgba[1];
923 drdz = result[3].trgba[0] - result[0].trgba[0];
924 dbdx = result[1].trgba[2] - result[0].trgba[2];
925 dgdx = result[1].trgba[1] - result[0].trgba[1];
926 drdy = result[2].trgba[0] - result[0].trgba[0];
927
928 force[0] = (dbdy - dgdz) * strength;
929 force[1] = (drdz - dbdx) * strength;
930 force[2] = (dgdx - drdy) * strength;
931 }
932 }
933 else {
934 zero_v3(force);
935 }
936
937 if (eff->pd->flag & PFIELD_TEX_2D) {
938 float fac = -dot_v3v3(force, efd->nor);
939 madd_v3_v3fl(force, efd->nor, fac);
940 }
941
942 if (eff->pd->flag & PFIELD_DO_LOCATION) {
943 add_v3_v3(total_force, force);
944 }
945}
947 EffectorData *efd,
948 EffectedPoint *point,
949 float *total_force)
950{
951 PartDeflect *pd = eff->pd;
952 RNG *rng = eff->rng;
953 float force[3] = {0, 0, 0};
954 float temp[3];
955 float fac;
956 float strength = pd->f_strength;
957 float damp = pd->f_damp;
958 float noise_factor = pd->f_noise;
959 float flow_falloff = efd->falloff;
960
961 if (noise_factor > 0.0f) {
962 strength += wind_func(rng, noise_factor);
963
965 damp += wind_func(rng, noise_factor);
966 }
967 }
968
969 copy_v3_v3(force, efd->vec_to_point);
970
971 switch (pd->forcefield) {
972 case PFIELD_WIND:
973 copy_v3_v3(force, efd->nor);
974 mul_v3_fl(force, strength * efd->falloff);
975 break;
976 case PFIELD_FORCE:
977 normalize_v3(force);
978 if (pd->flag & PFIELD_GRAVITATION) { /* Option: Multiply by 1/distance^2 */
979 if (efd->distance < FLT_EPSILON) {
980 strength = 0.0f;
981 }
982 else {
983 strength *= powf(efd->distance, -2.0f);
984 }
985 }
986 mul_v3_fl(force, strength * efd->falloff);
987 break;
988 case PFIELD_VORTEX:
989 /* old vortex force */
990 if (pd->shape == PFIELD_SHAPE_POINT) {
991 cross_v3_v3v3(force, efd->nor, efd->vec_to_point);
992 normalize_v3(force);
993 mul_v3_fl(force, strength * efd->distance * efd->falloff);
994 }
995 else {
996 /* new vortex force */
997 cross_v3_v3v3(temp, efd->nor2, efd->vec_to_point2);
998 mul_v3_fl(temp, strength * efd->falloff);
999
1000 cross_v3_v3v3(force, efd->nor2, temp);
1001 mul_v3_fl(force, strength * efd->falloff);
1002
1003 madd_v3_v3fl(temp, point->vel, -point->vel_to_sec);
1004 add_v3_v3(force, temp);
1005 }
1006 break;
1007 case PFIELD_MAGNET:
1009 /* magnetic field of a moving charge */
1010 cross_v3_v3v3(temp, efd->nor, efd->vec_to_point);
1011 }
1012 else {
1013 copy_v3_v3(temp, efd->nor);
1014 }
1015
1016 normalize_v3(temp);
1017 mul_v3_fl(temp, strength * efd->falloff);
1018 cross_v3_v3v3(force, point->vel, temp);
1019 mul_v3_fl(force, point->vel_to_sec);
1020 break;
1021 case PFIELD_HARMONIC:
1022 mul_v3_fl(force, -strength * efd->falloff);
1023 copy_v3_v3(temp, point->vel);
1024 mul_v3_fl(temp, -damp * 2.0f * sqrtf(fabsf(strength)) * point->vel_to_sec);
1025 add_v3_v3(force, temp);
1026 break;
1027 case PFIELD_CHARGE:
1028 mul_v3_fl(force, point->charge * strength * efd->falloff);
1029 break;
1030 case PFIELD_LENNARDJ:
1031 fac = pow((efd->size + point->size) / efd->distance, 6.0);
1032
1033 fac = -fac * (1.0f - fac) / efd->distance;
1034
1035 /* limit the repulsive term drastically to avoid huge forces */
1036 fac = ((fac > 2.0f) ? 2.0f : fac);
1037
1038 mul_v3_fl(force, strength * fac);
1039 break;
1040 case PFIELD_BOID:
1041 /* Boid field is handled completely in boids code. */
1042 return;
1043 case PFIELD_TURBULENCE:
1044 if (pd->flag & PFIELD_GLOBAL_CO) {
1045 copy_v3_v3(temp, point->loc);
1046 }
1047 else {
1048 add_v3_v3v3(temp, efd->vec_to_point2, efd->nor2);
1049 }
1050 force[0] = -1.0f + 2.0f * BLI_noise_generic_turbulence(
1051 pd->f_size, temp[0], temp[1], temp[2], 2, false, 2);
1052 force[1] = -1.0f + 2.0f * BLI_noise_generic_turbulence(
1053 pd->f_size, temp[1], temp[2], temp[0], 2, false, 2);
1054 force[2] = -1.0f + 2.0f * BLI_noise_generic_turbulence(
1055 pd->f_size, temp[2], temp[0], temp[1], 2, false, 2);
1056 mul_v3_fl(force, strength * efd->falloff);
1057 break;
1058 case PFIELD_DRAG:
1059 copy_v3_v3(force, point->vel);
1060 fac = normalize_v3(force) * point->vel_to_sec;
1061
1062 strength = std::min(strength, 2.0f);
1063 damp = std::min(damp, 2.0f);
1064
1065 mul_v3_fl(force, -efd->falloff * fac * (strength * fac + damp));
1066 break;
1067 case PFIELD_FLUIDFLOW:
1068 zero_v3(force);
1069 flow_falloff = 0;
1070#ifdef WITH_FLUID
1071 if (pd->f_source) {
1072 const float density = BKE_fluid_get_velocity_at(pd->f_source, point->loc, force);
1073 if (density >= 0.0f) {
1074 float influence = strength * efd->falloff;
1075 if (pd->flag & PFIELD_SMOKE_DENSITY) {
1076 influence *= density;
1077 }
1078 mul_v3_fl(force, influence);
1079 flow_falloff = influence;
1080 }
1081 }
1082#endif
1083 break;
1084 }
1085
1086 if (pd->flag & PFIELD_DO_LOCATION) {
1087 madd_v3_v3fl(total_force, force, 1.0f / point->vel_to_sec);
1088
1089 if (!ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG) && pd->f_flow != 0.0f) {
1090 madd_v3_v3fl(total_force, point->vel, -pd->f_flow * flow_falloff);
1091 }
1092 }
1093
1094 if (pd->flag & PFIELD_DO_ROTATION && point->ave && point->rot) {
1095 float xvec[3] = {1.0f, 0.0f, 0.0f};
1096 float dave[3];
1097 mul_qt_v3(point->rot, xvec);
1098 cross_v3_v3v3(dave, xvec, force);
1099 if (pd->f_flow != 0.0f) {
1100 madd_v3_v3fl(dave, point->ave, -pd->f_flow * efd->falloff);
1101 }
1102 add_v3_v3(point->ave, dave);
1103 }
1104}
1105
1107 ListBase *colliders,
1108 EffectorWeights *weights,
1109 EffectedPoint *point,
1110 float *force,
1111 float *wind_force,
1112 float *impulse)
1113{
1114 /* WARNING(@ideasman42): historic comment?
1115 * Many of these parameters don't exist!
1116 *
1117 * `scene` = scene where it runs in, for time and stuff.
1118 * `lb` = listbase with objects that take part in effecting.
1119 * `opco` = global coord, as input.
1120 * `force` = accumulator for force.
1121 * `wind_force` = accumulator for force only acting perpendicular to a surface.
1122 * `speed` = actual current speed which can be altered.
1123 * `cur_time` = "external" time in frames, is constant for static particles.
1124 * `loc_time` = "local" time in frames, range <0-1> for the lifetime of particle.
1125 * `par_layer` = layer the caller is in.
1126 * `flags` = only used for soft-body wind now.
1127 * `guide` = old speed of particle.
1128 */
1129
1130 /*
1131 * Modifies the force on a particle according to its
1132 * relation with the effector object
1133 * Different kind of effectors include:
1134 * - Force-fields: Gravity-like attractor
1135 * (force power is related to the inverse of distance to the power of a falloff value)
1136 * - Vortex fields: swirling effectors
1137 * (particles rotate around Z-axis of the object. otherwise, same relation as)
1138 * (Force-fields, but this is not done through a force/acceleration)
1139 * - Guide: particles on a path
1140 * (particles are guided along a curve bezier or old nurbs)
1141 * (is independent of other effectors)
1142 */
1143 EffectorData efd;
1144 int p = 0, tot = 1, step = 1;
1145
1146 /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
1147 /* Check for min distance here? (yes would be cool to add that, ton) */
1148
1149 if (effectors) {
1150 LISTBASE_FOREACH (EffectorCache *, eff, effectors) {
1151 /* object effectors were fully checked to be OK to evaluate! */
1152
1153 get_effector_tot(eff, &efd, point, &tot, &p, &step);
1154
1155 for (; p < tot; p += step) {
1156 if (get_effector_data(eff, &efd, point, 0)) {
1157 efd.falloff = effector_falloff(eff, &efd, point, weights);
1158
1159 if (efd.falloff > 0.0f) {
1160 efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point);
1161 }
1162 if (efd.falloff > 0.0f) {
1163 float out_force[3] = {0, 0, 0};
1164
1165 if (eff->pd->forcefield == PFIELD_TEXTURE) {
1166 do_texture_effector(eff, &efd, point, out_force);
1167 }
1168 else {
1169 do_physical_effector(eff, &efd, point, out_force);
1170
1171 /* for softbody backward compatibility */
1172 if (point->flag & PE_WIND_AS_SPEED && impulse) {
1173 sub_v3_v3v3(impulse, impulse, out_force);
1174 }
1175 }
1176
1177 if (wind_force) {
1178 madd_v3_v3fl(force, out_force, 1.0f - eff->pd->f_wind_factor);
1179 madd_v3_v3fl(wind_force, out_force, eff->pd->f_wind_factor);
1180 }
1181 else {
1182 add_v3_v3(force, out_force);
1183 }
1184 }
1185 }
1186 else if (eff->flag & PE_VELOCITY_TO_IMPULSE && impulse) {
1187 /* special case for harmonic effector */
1188 add_v3_v3v3(impulse, impulse, efd.vel);
1189 }
1190 }
1191 }
1192 }
1193}
1194
1195/* ======== Simulation Debugging ======== */
1196
1198
1203
1205{
1206#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
1207
1208 uint a, b, c;
1209
1210 a = b = c = 0xdeadbeef + (2 << 2) + 13;
1211 a += kx;
1212 b += ky;
1213
1214 c ^= b;
1215 c -= rot(b, 14);
1216 a ^= c;
1217 a -= rot(c, 11);
1218 b ^= a;
1219 b -= rot(a, 25);
1220 c ^= b;
1221 c -= rot(b, 16);
1222 a ^= c;
1223 a -= rot(c, 4);
1224 b ^= a;
1225 b -= rot(a, 14);
1226 c ^= b;
1227 c -= rot(b, 24);
1228
1229 return c;
1230
1231#undef rot
1232}
1233
1234static uint debug_element_hash(const void *key)
1235{
1236 const SimDebugElement *elem = static_cast<const SimDebugElement *>(key);
1237 return elem->hash;
1238}
1239
1240static bool debug_element_compare(const void *a, const void *b)
1241{
1242 const SimDebugElement *elem1 = static_cast<const SimDebugElement *>(a);
1243 const SimDebugElement *elem2 = static_cast<const SimDebugElement *>(b);
1244
1245 if (elem1->hash == elem2->hash) {
1246 return false;
1247 }
1248 return true;
1249}
1250
1251static void debug_element_free(void *val)
1252{
1253 SimDebugElement *elem = static_cast<SimDebugElement *>(val);
1254 MEM_freeN(elem);
1255}
1256
1258{
1259 if (enable) {
1260 if (!_sim_debug_data) {
1261 _sim_debug_data = MEM_callocN<SimDebugData>("sim debug data");
1263 debug_element_hash, debug_element_compare, "sim debug element hash");
1264 }
1265 }
1266 else {
1268 }
1269}
1270
1272{
1273 return _sim_debug_data != nullptr;
1274}
1275
1277{
1278 if (_sim_debug_data) {
1279 if (_sim_debug_data->gh) {
1281 }
1283 }
1284}
1285
1286static void debug_data_insert(SimDebugData *debug_data, SimDebugElement *elem)
1287{
1288 SimDebugElement *old_elem = static_cast<SimDebugElement *>(
1289 BLI_ghash_lookup(debug_data->gh, elem));
1290 if (old_elem) {
1291 *old_elem = *elem;
1292 MEM_freeN(elem);
1293 }
1294 else {
1295 BLI_ghash_insert(debug_data->gh, elem, elem);
1296 }
1297}
1298
1300 const float v1[3],
1301 const float v2[3],
1302 const char *str,
1303 float r,
1304 float g,
1305 float b,
1306 const char *category,
1307 uint hash)
1308{
1309 uint category_hash = BLI_ghashutil_strhash_p(category);
1310 SimDebugElement *elem;
1311
1312 if (!_sim_debug_data) {
1313 if (G.debug & G_DEBUG_SIMDATA) {
1315 }
1316 else {
1317 return;
1318 }
1319 }
1320
1321 elem = MEM_callocN<SimDebugElement>("sim debug data element");
1322 elem->type = type;
1323 elem->category_hash = category_hash;
1324 elem->hash = hash;
1325 elem->color[0] = r;
1326 elem->color[1] = g;
1327 elem->color[2] = b;
1328 if (v1) {
1329 copy_v3_v3(elem->v1, v1);
1330 }
1331 else {
1332 zero_v3(elem->v1);
1333 }
1334 if (v2) {
1335 copy_v3_v3(elem->v2, v2);
1336 }
1337 else {
1338 zero_v3(elem->v2);
1339 }
1340 if (str) {
1341 STRNCPY(elem->str, str);
1342 }
1343 else {
1344 elem->str[0] = '\0';
1345 }
1346
1348}
1349
1351{
1352 SimDebugElement dummy;
1353 if (!_sim_debug_data) {
1354 return;
1355 }
1356 dummy.hash = hash;
1358}
1359
1361{
1362 if (!_sim_debug_data) {
1363 return;
1364 }
1365 if (_sim_debug_data->gh) {
1367 }
1368}
1369
1370void BKE_sim_debug_data_clear_category(const char *category)
1371{
1372 int category_hash = int(BLI_ghashutil_strhash_p(category));
1373
1374 if (!_sim_debug_data) {
1375 return;
1376 }
1377
1378 if (_sim_debug_data->gh) {
1379 GHashIterator iter;
1381 while (!BLI_ghashIterator_done(&iter)) {
1382 const SimDebugElement *elem = static_cast<const SimDebugElement *>(
1384
1385 /* Removing invalidates the current iterator, so step before removing. */
1387
1388 if (elem->category_hash == category_hash) {
1390 }
1391 }
1392 }
1393}
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)
Base * BKE_collection_or_layer_objects(const Scene *scene, ViewLayer *view_layer, Collection *collection)
void BKE_collider_cache_free(struct ListBase **colliders)
struct ListBase * BKE_collider_cache_create(struct Depsgraph *depsgraph, struct Object *self, struct Collection *collection)
display list (or rather multi purpose list) stuff.
void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, bool for_render)
SimDebugData * _sim_debug_data
Definition effect.cc:1197
#define PE_VELOCITY_TO_IMPULSE
Definition BKE_effect.h:169
#define PE_USE_NORMAL_DATA
Definition BKE_effect.h:166
#define PE_WIND_AS_SPEED
Definition BKE_effect.h:165
float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3])
@ G_DEBUG_SIMDATA
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, bool use_render_params)
Definition particle.cc:710
float psys_get_timestep(struct ParticleSimulationData *sim)
Definition particle.cc:4467
void psys_update_particle_tree(struct ParticleSystem *psys, float cfra)
bool psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, bool always)
Definition particle.cc:4879
unsigned int BLI_ghashutil_uinthash(unsigned int key)
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition BLI_ghash.cc:911
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:855
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:299
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:686
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:787
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
Definition BLI_ghash.cc:895
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:307
#define BVH_RAYCAST_DEFAULT
@ BVH_RAYCAST_WATERTIGHT
int BLI_bvhtree_ray_cast_ex(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata, int flag)
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
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
MINLINE float safe_acosf(float a)
#define RAD2DEGF(_rad)
void mul_m4_v3(const float M[4][4], float r[3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void mul_qt_v3(const float q[4], float r[3])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
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])
MINLINE void negate_v3_v3(float r[3], const float a[3])
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
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
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
float BLI_noise_generic_turbulence(float noisesize, float x, float y, float z, int oct, bool hard, int noisebasis)
Definition noise_c.cc:1210
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
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:88
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
unsigned int uint
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
#define ELEM(...)
@ DAG_EVAL_RENDER
ListBase * DEG_get_effector_relations(const Depsgraph *depsgraph, Collection *collection)
float DEG_get_ctime(const Depsgraph *graph)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ CU_PATH
@ BASE_ENABLED_RENDER
@ BASE_ENABLED_VIEWPORT
These structs are the foundation for all linked lists in the library system.
@ eModifierType_Surface
@ PFIELD_FALL_SPHERE
@ NUM_PFIELD_TYPES
@ PFIELD_FLUIDFLOW
@ PFIELD_HARMONIC
@ PFIELD_TURBULENCE
@ PFIELD_LENNARDJ
@ PFIELD_MULTIPLE_SPRINGS
@ PFIELD_SMOKE_DENSITY
@ PFIELD_TEX_OBJECT
@ PFIELD_DO_ROTATION
@ PFIELD_DO_LOCATION
@ PFIELD_VISIBILITY
@ PFIELD_CLOTH_USE_CULLING
@ PFIELD_GRAVITATION
@ PFIELD_SHAPE_LINE
@ PFIELD_SHAPE_PLANE
@ PFIELD_SHAPE_SURFACE
@ PFIELD_SHAPE_POINTS
@ PFIELD_SHAPE_POINT
Object is a sort of wrapper for general info.
@ OB_CURVES_LEGACY
@ PART_ROT_DYN
@ PART_SELF_EFFECT
@ TEX_RGB
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
constexpr const T * data() const
Definition BLI_span.hh:215
nullptr float
#define powf(x, y)
#define offsetof(t, d)
bool closest_point_on_surface(SurfaceModifierData *surmd, const float co[3], float surface_co[3], float surface_nor[3], float surface_vel[3])
Definition effect.cc:635
ListBase * BKE_effector_relations_create(Depsgraph *depsgraph, const Scene *scene, ViewLayer *view_layer, Collection *collection)
Definition effect.cc:200
void BKE_sim_debug_data_add_element(int type, const float v1[3], const float v2[3], const char *str, float r, float g, float b, const char *category, uint hash)
Definition effect.cc:1299
EffectorWeights * BKE_effector_add_weights(Collection *collection)
Definition effect.cc:58
static bool is_effector_relevant(PartDeflect *pd, EffectorWeights *weights, bool use_rotation)
Definition effect.cc:300
void BKE_sim_debug_data_clear_category(const char *category)
Definition effect.cc:1370
static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force)
Definition effect.cc:854
static void debug_data_insert(SimDebugData *debug_data, SimDebugElement *elem)
Definition effect.cc:1286
bool BKE_sim_debug_data_get_enabled()
Definition effect.cc:1271
void BKE_effectors_free(ListBase *lb)
Definition effect.cc:361
static bool is_effector_enabled(PartDeflect *pd, bool use_rotation)
Definition effect.cc:248
uint BKE_sim_debug_data_hash(int i)
Definition effect.cc:1199
static uint debug_element_hash(const void *key)
Definition effect.cc:1234
static bool debug_element_compare(const void *a, const void *b)
Definition effect.cc:1240
void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
Definition effect.cc:414
void pd_point_from_particle(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, EffectedPoint *point)
Definition effect.cc:378
static float falloff_func_dist(PartDeflect *pd, float fac)
Definition effect.cc:566
static void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force)
Definition effect.cc:946
static void add_effector_evaluation(ListBase **effectors, Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd)
Definition effect.cc:177
PartDeflect * BKE_partdeflect_new(int type)
Definition effect.cc:71
void BKE_effector_relations_free(ListBase *lb)
Definition effect.cc:239
void BKE_sim_debug_data_set_enabled(bool enable)
Definition effect.cc:1257
void BKE_partdeflect_free(PartDeflect *pd)
Definition effect.cc:119
void BKE_sim_debug_data_remove_element(uint hash)
Definition effect.cc:1350
static float wind_func(RNG *rng, float strength)
Definition effect.cc:529
void BKE_effectors_apply(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *wind_force, float *impulse)
Definition effect.cc:1106
static void eff_tri_ray_hit(void *, int, const BVHTreeRay *, BVHTreeRayHit *hit)
Definition effect.cc:450
static void add_effector_relation(ListBase *relations, Object *ob, ParticleSystem *psys, PartDeflect *pd)
Definition effect.cc:164
void BKE_sim_debug_data_clear()
Definition effect.cc:1360
#define rot(x, k)
static void debug_element_free(void *val)
Definition effect.cc:1251
static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p, int *step)
Definition effect.cc:807
static bool is_effector_nonzero_strength(PartDeflect *pd)
Definition effect.cc:269
void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
Definition effect.cc:429
PartDeflect * BKE_partdeflect_copy(const PartDeflect *pd_src)
Definition effect.cc:110
bool get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int real_velocity)
Definition effect.cc:671
float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *, EffectorWeights *weights)
Definition effect.cc:586
ListBase * BKE_effectors_create(Depsgraph *depsgraph, Object *ob_src, ParticleSystem *psys_src, EffectorWeights *weights, bool use_rotation)
Definition effect.cc:306
uint BKE_sim_debug_data_hash_combine(uint kx, uint ky)
Definition effect.cc:1204
static void precalculate_effector(Depsgraph *depsgraph, EffectorCache *eff)
Definition effect.cc:129
static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, EffectorData *efd, EffectedPoint *point)
Definition effect.cc:463
static float falloff_func(float fac, int usemin, float mindist, int usemax, float maxdist, float power)
Definition effect.cc:547
static float falloff_func_rad(PartDeflect *pd, float fac)
Definition effect.cc:576
void BKE_sim_debug_data_free()
Definition effect.cc:1276
#define str(s)
IMETHOD void random(Vector &a)
addDelta operator for displacement rotational velocity.
Definition frames.inl:1282
uint col
#define pow
constexpr T sign(T) RET
#define ceil
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
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
ccl_device_inline float2 power(const float2 v, const float e)
static ulong state[N]
#define G(x, y, z)
VecBase< int32_t, 3 > int3
#define hash
Definition noise_c.cc:154
const char * name
return ret
#define fabsf
#define sqrtf
closure color absorption() BUILTIN
#define FLT_MAX
Definition stdcycles.h:14
struct Base * next
short flag
struct Object * object
float vel_to_sec
Definition BKE_effect.h:30
float * vel
Definition BKE_effect.h:26
struct ParticleSystem * psys
Definition BKE_effect.h:38
float vel_to_frame
Definition BKE_effect.h:29
float * loc
Definition BKE_effect.h:25
unsigned int flag
Definition BKE_effect.h:35
float * rot
Definition BKE_effect.h:28
float * ave
Definition BKE_effect.h:27
struct ParticleSystem * psys
Definition BKE_effect.h:71
struct RNG * rng
Definition BKE_effect.h:77
struct SurfaceModifierData * surmd
Definition BKE_effect.h:72
float guide_dir[3]
Definition BKE_effect.h:81
float guide_loc[4]
Definition BKE_effect.h:81
float guide_radius
Definition BKE_effect.h:81
struct Scene * scene
Definition BKE_effect.h:69
struct PartDeflect * pd
Definition BKE_effect.h:74
struct Object * ob
Definition BKE_effect.h:70
struct Depsgraph * depsgraph
Definition BKE_effect.h:68
float loc[3]
Definition BKE_effect.h:48
float distance
Definition BKE_effect.h:53
float vec_to_point[3]
Definition BKE_effect.h:52
float vec_to_point2[3]
Definition BKE_effect.h:59
float nor[3]
Definition BKE_effect.h:49
float falloff
Definition BKE_effect.h:53
float vel[3]
Definition BKE_effect.h:50
float nor2[3]
Definition BKE_effect.h:59
struct ParticleSystem * psys
Definition BKE_effect.h:91
struct PartDeflect * pd
Definition BKE_effect.h:92
struct Object * ob
Definition BKE_effect.h:90
struct Collection * group
int verts_num
ListBase particlesystem
ObjectRuntimeHandle * runtime
struct PartDeflect * pd
struct Object * f_source
struct PartDeflect * pd2
struct PartDeflect * pd
struct Depsgraph * depsgraph
struct Scene * scene
struct ParticleSystem * psys
struct Object * ob
ParticleData * particles
ParticleSettings * part
Definition rand.cc:33
struct RenderData r
struct GHash * gh
Definition BKE_effect.h:218
unsigned int category_hash
Definition BKE_effect.h:199
unsigned int hash
Definition BKE_effect.h:200
BVHTreeFromMeshHandle * bvhtree
SurfaceModifierData_Runtime runtime
BVHTree_NearestPointCallback nearest_callback
i
Definition text_draw.cc:230
int multitex_ext(Tex *tex, const float texvec[3], TexResult *texres, const short thread, ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
uint len