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
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_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,
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,
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,
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,
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,
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,
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)
SimDebugData * _sim_debug_data
Definition effect.cc:1201
#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)
@ BVH_RAYCAST_WATERTIGHT
Definition BLI_kdopbvh.h:89
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
@ NUM_PFIELD_TYPES
@ PFIELD_FLUIDFLOW
@ PFIELD_HARMONIC
@ PFIELD_TURBULENCE
@ PFIELD_LENNARDJ
@ PFIELD_MULTIPLE_SPRINGS
@ PFIELD_SMOKE_DENSITY
@ PFIELD_TEX_OBJECT
@ PFIELD_DO_ROTATION
@ PFIELD_DO_LOCATION
@ PFIELD_VISIBILITY
@ PFIELD_CLOTH_USE_CULLING
@ PFIELD_GRAVITATION
@ PFIELD_SHAPE_LINE
@ PFIELD_SHAPE_PLANE
@ PFIELD_SHAPE_SURFACE
@ PFIELD_SHAPE_POINTS
@ PFIELD_SHAPE_POINT
@ 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.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
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:216
local_group_size(16, 16) .push_constant(Type b
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
#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
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)
IMETHOD void random(Vector &a)
addDelta operator for displacement rotational velocity.
Definition frames.inl:1282
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)
VecBase< int32_t, 3 > int3
#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
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: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)