Blender V4.3
depsgraph_physics.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_compiler_compat.h"
16#include "BLI_listbase.h"
17
18#include "BKE_collision.h"
19#include "BKE_effect.h"
20#include "BKE_modifier.hh"
21
24#include "DNA_object_types.h"
25
29
30#include "depsgraph.hh"
31
32namespace deg = blender::deg;
33
34/*************************** Evaluation Query API *****************************/
35
37{
38 switch (modifier_type) {
45 }
46
47 BLI_assert_msg(0, "Unknown collision modifier type");
49}
50/* Get ID from an ID type object, in a safe manner. This means that object can be nullptr,
51 * in which case the function returns nullptr.
52 */
53template<class T> static ID *object_id_safe(T *object)
54{
55 if (object == nullptr) {
56 return nullptr;
57 }
58 return &object->id;
59}
60
61ListBase *DEG_get_effector_relations(const Depsgraph *graph, Collection *collection)
62{
63 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
65 if (hash == nullptr) {
66 return nullptr;
67 }
68 /* NOTE: nullptr is a valid lookup key here as it means that the relation is not bound to a
69 * specific collection. */
70 ID *collection_orig = DEG_get_original_id(object_id_safe(collection));
71 return hash->lookup_default(collection_orig, nullptr);
72}
73
74ListBase *DEG_get_collision_relations(const Depsgraph *graph,
75 Collection *collection,
76 uint modifier_type)
77{
78 const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
79 const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
81 if (hash == nullptr) {
82 return nullptr;
83 }
84 /* NOTE: nullptr is a valid lookup key here as it means that the relation is not bound to a
85 * specific collection. */
86 ID *collection_orig = DEG_get_original_id(object_id_safe(collection));
87 return hash->lookup_default(collection_orig, nullptr);
88}
89
90/********************** Depsgraph Building API ************************/
91
92void DEG_add_collision_relations(DepsNodeHandle *handle,
93 Object *object,
94 Collection *collection,
95 uint modifier_type,
96 DEG_CollobjFilterFunction filter_function,
97 const char *name)
98{
99 Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
101 ListBase *relations = build_collision_relations(deg_graph, collection, modifier_type);
102 LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
103 Object *ob1 = relation->ob;
104 if (ob1 == object) {
105 continue;
106 }
107 if (filter_function == nullptr ||
108 filter_function(ob1, BKE_modifiers_findby_type(ob1, (ModifierType)modifier_type)))
109 {
112 }
113 }
114}
115
116void DEG_add_forcefield_relations(DepsNodeHandle *handle,
117 Object *object,
118 EffectorWeights *effector_weights,
119 bool add_absorption,
120 int skip_forcefield,
121 const char *name)
122{
123 Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
125 ListBase *relations = build_effector_relations(deg_graph, effector_weights->group);
126 LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
127 if (relation->ob == object) {
128 continue;
129 }
130 if (relation->pd->forcefield == skip_forcefield) {
131 continue;
132 }
133
134 /* Relation to forcefield object, optionally including geometry.
135 * Use special point cache relations for automatic cache clearing. */
137
138 if (relation->psys || ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
139 relation->pd->forcefield == PFIELD_GUIDE)
140 {
141 /* TODO(sergey): Consider going more granular with more dedicated
142 * particle system operation. */
143 DEG_add_object_pointcache_relation(handle, relation->ob, DEG_OB_COMP_GEOMETRY, name);
144 }
145
146 /* Smoke flow relations. */
147 if (relation->pd->forcefield == PFIELD_FLUIDFLOW && relation->pd->f_source != nullptr) {
149 handle, relation->pd->f_source, DEG_OB_COMP_TRANSFORM, "Fluid Force Domain");
151 handle, relation->pd->f_source, DEG_OB_COMP_GEOMETRY, "Fluid Force Domain");
152 }
153
154 /* Absorption forces need collision relation. */
155 if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
157 handle, object, nullptr, eModifierType_Collision, nullptr, "Force Absorption");
158 }
159 }
160}
161
162/******************************** Internal API ********************************/
163
164namespace blender::deg {
165
167{
168 Map<const ID *, ListBase *> *hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR];
169 if (hash == nullptr) {
170 graph->physics_relations[DEG_PHYSICS_EFFECTOR] = new Map<const ID *, ListBase *>();
171 hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR];
172 }
173 /* If collection is nullptr still use it as a key.
174 * In this case the BKE_effector_relations_create() will create relates for all bases in the
175 * view layer.
176 */
177 ID *collection_id = object_id_safe(collection);
178 return hash->lookup_or_add_cb(collection_id, [&]() {
179 ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph);
180 return BKE_effector_relations_create(depsgraph, graph->scene, graph->view_layer, collection);
181 });
182}
183
184ListBase *build_collision_relations(Depsgraph *graph, Collection *collection, uint modifier_type)
185{
186 const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
187 Map<const ID *, ListBase *> *hash = graph->physics_relations[type];
188 if (hash == nullptr) {
189 graph->physics_relations[type] = new Map<const ID *, ListBase *>();
190 hash = graph->physics_relations[type];
191 }
192 /* If collection is nullptr still use it as a key.
193 * In this case the BKE_collision_relations_create() will create relates for all bases in the
194 * view layer.
195 */
196 ID *collection_id = object_id_safe(collection);
197 return hash->lookup_or_add_cb(collection_id, [&]() {
198 ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph);
199 return BKE_collision_relations_create(depsgraph, collection, modifier_type);
200 });
201}
202
204{
205 for (int i = 0; i < DEG_PHYSICS_RELATIONS_NUM; i++) {
206 Map<const ID *, ListBase *> *hash = graph->physics_relations[i];
207 if (hash) {
209
210 switch (type) {
212 for (ListBase *list : hash->values()) {
214 }
215 break;
219 for (ListBase *list : hash->values()) {
221 }
222 break;
224 break;
225 }
226 delete hash;
227 graph->physics_relations[i] = nullptr;
228 }
229 }
230}
231
232} // namespace blender::deg
struct ListBase * BKE_collision_relations_create(struct Depsgraph *depsgraph, struct Collection *collection, unsigned int modifier_type)
void BKE_collision_relations_free(struct ListBase *relations)
struct ListBase * BKE_effector_relations_create(struct Depsgraph *depsgraph, const struct Scene *scene, struct ViewLayer *view_layer, struct Collection *collection)
void BKE_effector_relations_free(struct ListBase *lb)
Definition effect.cc:242
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define LISTBASE_FOREACH(type, var, list)
unsigned int uint
#define ELEM(...)
void DEG_add_object_pointcache_relation(DepsNodeHandle *node_handle, Object *object, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
Depsgraph * DEG_get_graph_from_handle(DepsNodeHandle *node_handle)
bool(*)(Object *obj, ModifierData *md) DEG_CollobjFilterFunction
@ DEG_PHYSICS_DYNAMIC_BRUSH
@ DEG_PHYSICS_SMOKE_COLLISION
@ DEG_PHYSICS_COLLISION
@ DEG_PHYSICS_RELATIONS_NUM
@ DEG_PHYSICS_EFFECTOR
ID * DEG_get_original_id(ID *id)
Object groups, one object can be in many groups at once.
@ eModifierType_Fluid
@ eModifierType_Collision
@ eModifierType_DynamicPaint
@ PFIELD_VISIBILITY
@ PFIELD_FLUIDFLOW
@ PFIELD_SHAPE_SURFACE
@ PFIELD_SHAPE_POINTS
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
Depsgraph * graph
const Depsgraph * depsgraph
void DEG_add_collision_relations(DepsNodeHandle *handle, Object *object, Collection *collection, uint modifier_type, DEG_CollobjFilterFunction filter_function, const char *name)
static ePhysicsRelationType modifier_to_relation_type(uint modifier_type)
ListBase * DEG_get_collision_relations(const Depsgraph *graph, Collection *collection, uint modifier_type)
ListBase * DEG_get_effector_relations(const Depsgraph *graph, Collection *collection)
void DEG_add_forcefield_relations(DepsNodeHandle *handle, Object *object, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
static ID * object_id_safe(T *object)
ListBase * build_collision_relations(Depsgraph *graph, Collection *collection, uint modifier_type)
ListBase * build_effector_relations(Depsgraph *graph, Collection *collection)
void clear_physics_relations(Depsgraph *graph)
#define hash
Definition noise.c:154
struct Collection * group
Definition DNA_ID.h:413
Map< const ID *, ListBase * > * physics_relations[DEG_PHYSICS_RELATIONS_NUM]
Definition depsgraph.hh:174