Blender V4.5
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(
886 eff->pd->tex, tex_co, nullptr, nullptr, 0, result, 0, nullptr, true, false);
887
888 if (hasrgb && mode == PFIELD_TEX_RGB) {
889 force[0] = (0.5f - result->trgba[0]) * strength;
890 force[1] = (0.5f - result->trgba[1]) * strength;
891 force[2] = (0.5f - result->trgba[2]) * strength;
892 }
893 else if (nabla != 0) {
894 strength /= nabla;
895
896 tex_co[0] += nabla;
897 multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 1, 0, nullptr, true, false);
898
899 tex_co[0] -= nabla;
900 tex_co[1] += nabla;
901 multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 2, 0, nullptr, true, false);
902
903 tex_co[1] -= nabla;
904 tex_co[2] += nabla;
905 multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 3, 0, nullptr, true, false);
906
907 if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */
908 /* generate intensity if texture only has rgb value */
909 if (hasrgb & TEX_RGB) {
910 for (int i = 0; i < 4; i++) {
911 result[i].tin = (1.0f / 3.0f) *
912 (result[i].trgba[0] + result[i].trgba[1] + result[i].trgba[2]);
913 }
914 }
915 force[0] = (result[0].tin - result[1].tin) * strength;
916 force[1] = (result[0].tin - result[2].tin) * strength;
917 force[2] = (result[0].tin - result[3].tin) * strength;
918 }
919 else { /*PFIELD_TEX_CURL*/
920 float dbdy, dgdz, drdz, dbdx, dgdx, drdy;
921
922 dbdy = result[2].trgba[2] - result[0].trgba[2];
923 dgdz = result[3].trgba[1] - result[0].trgba[1];
924 drdz = result[3].trgba[0] - result[0].trgba[0];
925 dbdx = result[1].trgba[2] - result[0].trgba[2];
926 dgdx = result[1].trgba[1] - result[0].trgba[1];
927 drdy = result[2].trgba[0] - result[0].trgba[0];
928
929 force[0] = (dbdy - dgdz) * strength;
930 force[1] = (drdz - dbdx) * strength;
931 force[2] = (dgdx - drdy) * strength;
932 }
933 }
934 else {
935 zero_v3(force);
936 }
937
938 if (eff->pd->flag & PFIELD_TEX_2D) {
939 float fac = -dot_v3v3(force, efd->nor);
940 madd_v3_v3fl(force, efd->nor, fac);
941 }
942
943 if (eff->pd->flag & PFIELD_DO_LOCATION) {
944 add_v3_v3(total_force, force);
945 }
946}
948 EffectorData *efd,
949 EffectedPoint *point,
950 float *total_force)
951{
952 PartDeflect *pd = eff->pd;
953 RNG *rng = eff->rng;
954 float force[3] = {0, 0, 0};
955 float temp[3];
956 float fac;
957 float strength = pd->f_strength;
958 float damp = pd->f_damp;
959 float noise_factor = pd->f_noise;
960 float flow_falloff = efd->falloff;
961
962 if (noise_factor > 0.0f) {
963 strength += wind_func(rng, noise_factor);
964
966 damp += wind_func(rng, noise_factor);
967 }
968 }
969
970 copy_v3_v3(force, efd->vec_to_point);
971
972 switch (pd->forcefield) {
973 case PFIELD_WIND:
974 copy_v3_v3(force, efd->nor);
975 mul_v3_fl(force, strength * efd->falloff);
976 break;
977 case PFIELD_FORCE:
978 normalize_v3(force);
979 if (pd->flag & PFIELD_GRAVITATION) { /* Option: Multiply by 1/distance^2 */
980 if (efd->distance < FLT_EPSILON) {
981 strength = 0.0f;
982 }
983 else {
984 strength *= powf(efd->distance, -2.0f);
985 }
986 }
987 mul_v3_fl(force, strength * efd->falloff);
988 break;
989 case PFIELD_VORTEX:
990 /* old vortex force */
991 if (pd->shape == PFIELD_SHAPE_POINT) {
992 cross_v3_v3v3(force, efd->nor, efd->vec_to_point);
993 normalize_v3(force);
994 mul_v3_fl(force, strength * efd->distance * efd->falloff);
995 }
996 else {
997 /* new vortex force */
998 cross_v3_v3v3(temp, efd->nor2, efd->vec_to_point2);
999 mul_v3_fl(temp, strength * efd->falloff);
1000
1001 cross_v3_v3v3(force, efd->nor2, temp);
1002 mul_v3_fl(force, strength * efd->falloff);
1003
1004 madd_v3_v3fl(temp, point->vel, -point->vel_to_sec);
1005 add_v3_v3(force, temp);
1006 }
1007 break;
1008 case PFIELD_MAGNET:
1010 /* magnetic field of a moving charge */
1011 cross_v3_v3v3(temp, efd->nor, efd->vec_to_point);
1012 }
1013 else {
1014 copy_v3_v3(temp, efd->nor);
1015 }
1016
1017 normalize_v3(temp);
1018 mul_v3_fl(temp, strength * efd->falloff);
1019 cross_v3_v3v3(force, point->vel, temp);
1020 mul_v3_fl(force, point->vel_to_sec);
1021 break;
1022 case PFIELD_HARMONIC:
1023 mul_v3_fl(force, -strength * efd->falloff);
1024 copy_v3_v3(temp, point->vel);
1025 mul_v3_fl(temp, -damp * 2.0f * sqrtf(fabsf(strength)) * point->vel_to_sec);
1026 add_v3_v3(force, temp);
1027 break;
1028 case PFIELD_CHARGE:
1029 mul_v3_fl(force, point->charge * strength * efd->falloff);
1030 break;
1031 case PFIELD_LENNARDJ:
1032 fac = pow((efd->size + point->size) / efd->distance, 6.0);
1033
1034 fac = -fac * (1.0f - fac) / efd->distance;
1035
1036 /* limit the repulsive term drastically to avoid huge forces */
1037 fac = ((fac > 2.0f) ? 2.0f : fac);
1038
1039 mul_v3_fl(force, strength * fac);
1040 break;
1041 case PFIELD_BOID:
1042 /* Boid field is handled completely in boids code. */
1043 return;
1044 case PFIELD_TURBULENCE:
1045 if (pd->flag & PFIELD_GLOBAL_CO) {
1046 copy_v3_v3(temp, point->loc);
1047 }
1048 else {
1049 add_v3_v3v3(temp, efd->vec_to_point2, efd->nor2);
1050 }
1051 force[0] = -1.0f + 2.0f * BLI_noise_generic_turbulence(
1052 pd->f_size, temp[0], temp[1], temp[2], 2, false, 2);
1053 force[1] = -1.0f + 2.0f * BLI_noise_generic_turbulence(
1054 pd->f_size, temp[1], temp[2], temp[0], 2, false, 2);
1055 force[2] = -1.0f + 2.0f * BLI_noise_generic_turbulence(
1056 pd->f_size, temp[2], temp[0], temp[1], 2, false, 2);
1057 mul_v3_fl(force, strength * efd->falloff);
1058 break;
1059 case PFIELD_DRAG:
1060 copy_v3_v3(force, point->vel);
1061 fac = normalize_v3(force) * point->vel_to_sec;
1062
1063 strength = std::min(strength, 2.0f);
1064 damp = std::min(damp, 2.0f);
1065
1066 mul_v3_fl(force, -efd->falloff * fac * (strength * fac + damp));
1067 break;
1068 case PFIELD_FLUIDFLOW:
1069 zero_v3(force);
1070 flow_falloff = 0;
1071#ifdef WITH_FLUID
1072 if (pd->f_source) {
1073 const float density = BKE_fluid_get_velocity_at(pd->f_source, point->loc, force);
1074 if (density >= 0.0f) {
1075 float influence = strength * efd->falloff;
1076 if (pd->flag & PFIELD_SMOKE_DENSITY) {
1077 influence *= density;
1078 }
1079 mul_v3_fl(force, influence);
1080 flow_falloff = influence;
1081 }
1082 }
1083#endif
1084 break;
1085 }
1086
1087 if (pd->flag & PFIELD_DO_LOCATION) {
1088 madd_v3_v3fl(total_force, force, 1.0f / point->vel_to_sec);
1089
1090 if (!ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG) && pd->f_flow != 0.0f) {
1091 madd_v3_v3fl(total_force, point->vel, -pd->f_flow * flow_falloff);
1092 }
1093 }
1094
1095 if (pd->flag & PFIELD_DO_ROTATION && point->ave && point->rot) {
1096 float xvec[3] = {1.0f, 0.0f, 0.0f};
1097 float dave[3];
1098 mul_qt_v3(point->rot, xvec);
1099 cross_v3_v3v3(dave, xvec, force);
1100 if (pd->f_flow != 0.0f) {
1101 madd_v3_v3fl(dave, point->ave, -pd->f_flow * efd->falloff);
1102 }
1103 add_v3_v3(point->ave, dave);
1104 }
1105}
1106
1108 ListBase *colliders,
1109 EffectorWeights *weights,
1110 EffectedPoint *point,
1111 float *force,
1112 float *wind_force,
1113 float *impulse)
1114{
1115 /* WARNING(@ideasman42): historic comment?
1116 * Many of these parameters don't exist!
1117 *
1118 * `scene` = scene where it runs in, for time and stuff.
1119 * `lb` = listbase with objects that take part in effecting.
1120 * `opco` = global coord, as input.
1121 * `force` = accumulator for force.
1122 * `wind_force` = accumulator for force only acting perpendicular to a surface.
1123 * `speed` = actual current speed which can be altered.
1124 * `cur_time` = "external" time in frames, is constant for static particles.
1125 * `loc_time` = "local" time in frames, range <0-1> for the lifetime of particle.
1126 * `par_layer` = layer the caller is in.
1127 * `flags` = only used for soft-body wind now.
1128 * `guide` = old speed of particle.
1129 */
1130
1131 /*
1132 * Modifies the force on a particle according to its
1133 * relation with the effector object
1134 * Different kind of effectors include:
1135 * - Force-fields: Gravity-like attractor
1136 * (force power is related to the inverse of distance to the power of a falloff value)
1137 * - Vortex fields: swirling effectors
1138 * (particles rotate around Z-axis of the object. otherwise, same relation as)
1139 * (Force-fields, but this is not done through a force/acceleration)
1140 * - Guide: particles on a path
1141 * (particles are guided along a curve bezier or old nurbs)
1142 * (is independent of other effectors)
1143 */
1144 EffectorData efd;
1145 int p = 0, tot = 1, step = 1;
1146
1147 /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
1148 /* Check for min distance here? (yes would be cool to add that, ton) */
1149
1150 if (effectors) {
1151 LISTBASE_FOREACH (EffectorCache *, eff, effectors) {
1152 /* object effectors were fully checked to be OK to evaluate! */
1153
1154 get_effector_tot(eff, &efd, point, &tot, &p, &step);
1155
1156 for (; p < tot; p += step) {
1157 if (get_effector_data(eff, &efd, point, 0)) {
1158 efd.falloff = effector_falloff(eff, &efd, point, weights);
1159
1160 if (efd.falloff > 0.0f) {
1161 efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point);
1162 }
1163 if (efd.falloff > 0.0f) {
1164 float out_force[3] = {0, 0, 0};
1165
1166 if (eff->pd->forcefield == PFIELD_TEXTURE) {
1167 do_texture_effector(eff, &efd, point, out_force);
1168 }
1169 else {
1170 do_physical_effector(eff, &efd, point, out_force);
1171
1172 /* for softbody backward compatibility */
1173 if (point->flag & PE_WIND_AS_SPEED && impulse) {
1174 sub_v3_v3v3(impulse, impulse, out_force);
1175 }
1176 }
1177
1178 if (wind_force) {
1179 madd_v3_v3fl(force, out_force, 1.0f - eff->pd->f_wind_factor);
1180 madd_v3_v3fl(wind_force, out_force, eff->pd->f_wind_factor);
1181 }
1182 else {
1183 add_v3_v3(force, out_force);
1184 }
1185 }
1186 }
1187 else if (eff->flag & PE_VELOCITY_TO_IMPULSE && impulse) {
1188 /* special case for harmonic effector */
1189 add_v3_v3v3(impulse, impulse, efd.vel);
1190 }
1191 }
1192 }
1193 }
1194}
1195
1196/* ======== Simulation Debugging ======== */
1197
1199
1204
1206{
1207#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
1208
1209 uint a, b, c;
1210
1211 a = b = c = 0xdeadbeef + (2 << 2) + 13;
1212 a += kx;
1213 b += ky;
1214
1215 c ^= b;
1216 c -= rot(b, 14);
1217 a ^= c;
1218 a -= rot(c, 11);
1219 b ^= a;
1220 b -= rot(a, 25);
1221 c ^= b;
1222 c -= rot(b, 16);
1223 a ^= c;
1224 a -= rot(c, 4);
1225 b ^= a;
1226 b -= rot(a, 14);
1227 c ^= b;
1228 c -= rot(b, 24);
1229
1230 return c;
1231
1232#undef rot
1233}
1234
1235static uint debug_element_hash(const void *key)
1236{
1237 const SimDebugElement *elem = static_cast<const SimDebugElement *>(key);
1238 return elem->hash;
1239}
1240
1241static bool debug_element_compare(const void *a, const void *b)
1242{
1243 const SimDebugElement *elem1 = static_cast<const SimDebugElement *>(a);
1244 const SimDebugElement *elem2 = static_cast<const SimDebugElement *>(b);
1245
1246 if (elem1->hash == elem2->hash) {
1247 return false;
1248 }
1249 return true;
1250}
1251
1252static void debug_element_free(void *val)
1253{
1254 SimDebugElement *elem = static_cast<SimDebugElement *>(val);
1255 MEM_freeN(elem);
1256}
1257
1259{
1260 if (enable) {
1261 if (!_sim_debug_data) {
1262 _sim_debug_data = MEM_callocN<SimDebugData>("sim debug data");
1264 debug_element_hash, debug_element_compare, "sim debug element hash");
1265 }
1266 }
1267 else {
1269 }
1270}
1271
1273{
1274 return _sim_debug_data != nullptr;
1275}
1276
1278{
1279 if (_sim_debug_data) {
1280 if (_sim_debug_data->gh) {
1282 }
1284 }
1285}
1286
1287static void debug_data_insert(SimDebugData *debug_data, SimDebugElement *elem)
1288{
1289 SimDebugElement *old_elem = static_cast<SimDebugElement *>(
1290 BLI_ghash_lookup(debug_data->gh, elem));
1291 if (old_elem) {
1292 *old_elem = *elem;
1293 MEM_freeN(elem);
1294 }
1295 else {
1296 BLI_ghash_insert(debug_data->gh, elem, elem);
1297 }
1298}
1299
1301 const float v1[3],
1302 const float v2[3],
1303 const char *str,
1304 float r,
1305 float g,
1306 float b,
1307 const char *category,
1308 uint hash)
1309{
1310 uint category_hash = BLI_ghashutil_strhash_p(category);
1311 SimDebugElement *elem;
1312
1313 if (!_sim_debug_data) {
1314 if (G.debug & G_DEBUG_SIMDATA) {
1316 }
1317 else {
1318 return;
1319 }
1320 }
1321
1322 elem = MEM_callocN<SimDebugElement>("sim debug data element");
1323 elem->type = type;
1324 elem->category_hash = category_hash;
1325 elem->hash = hash;
1326 elem->color[0] = r;
1327 elem->color[1] = g;
1328 elem->color[2] = b;
1329 if (v1) {
1330 copy_v3_v3(elem->v1, v1);
1331 }
1332 else {
1333 zero_v3(elem->v1);
1334 }
1335 if (v2) {
1336 copy_v3_v3(elem->v2, v2);
1337 }
1338 else {
1339 zero_v3(elem->v2);
1340 }
1341 if (str) {
1342 STRNCPY(elem->str, str);
1343 }
1344 else {
1345 elem->str[0] = '\0';
1346 }
1347
1349}
1350
1352{
1353 SimDebugElement dummy;
1354 if (!_sim_debug_data) {
1355 return;
1356 }
1357 dummy.hash = hash;
1359}
1360
1362{
1363 if (!_sim_debug_data) {
1364 return;
1365 }
1366 if (_sim_debug_data->gh) {
1368 }
1369}
1370
1371void BKE_sim_debug_data_clear_category(const char *category)
1372{
1373 int category_hash = int(BLI_ghashutil_strhash_p(category));
1374
1375 if (!_sim_debug_data) {
1376 return;
1377 }
1378
1379 if (_sim_debug_data->gh) {
1380 GHashIterator iter;
1382 while (!BLI_ghashIterator_done(&iter)) {
1383 const SimDebugElement *elem = static_cast<const SimDebugElement *>(
1385
1386 /* Removing invalidates the current iterator, so step before removing. */
1388
1389 if (elem->category_hash == category_hash) {
1391 }
1392 }
1393 }
1394}
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:1198
#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:709
float psys_get_timestep(struct ParticleSimulationData *sim)
Definition particle.cc:4465
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:4877
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
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)
@ BVH_RAYCAST_WATERTIGHT
#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:688
unsigned int uint
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:65
#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
@ NUM_PFIELD_TYPES
@ PFIELD_FLUIDFLOW
@ PFIELD_HARMONIC
@ PFIELD_TURBULENCE
@ PFIELD_LENNARDJ
@ PFIELD_SHAPE_LINE
@ PFIELD_SHAPE_PLANE
@ PFIELD_SHAPE_SURFACE
@ PFIELD_SHAPE_POINTS
@ PFIELD_SHAPE_POINT
@ PFIELD_MULTIPLE_SPRINGS
@ PFIELD_SMOKE_DENSITY
@ PFIELD_TEX_OBJECT
@ PFIELD_DO_ROTATION
@ PFIELD_DO_LOCATION
@ PFIELD_VISIBILITY
@ PFIELD_CLOTH_USE_CULLING
@ PFIELD_GRAVITATION
@ PFIELD_FALL_SPHERE
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
#define powf(x, y)
#define offsetof(t, d)
#define fabsf(x)
#define sqrtf(x)
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:1300
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:1371
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:1287
bool BKE_sim_debug_data_get_enabled()
Definition effect.cc:1272
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:1200
static uint debug_element_hash(const void *key)
Definition effect.cc:1235
static bool debug_element_compare(const void *a, const void *b)
Definition effect.cc:1241
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:947
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:1258
void BKE_partdeflect_free(PartDeflect *pd)
Definition effect.cc:119
void BKE_sim_debug_data_remove_element(uint hash)
Definition effect.cc:1351
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:1107
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:1361
#define rot(x, k)
static void debug_element_free(void *val)
Definition effect.cc:1252
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:1205
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:1277
#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
return ret
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], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
uint len