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