Blender  V2.93
depsgraph_physics.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2018 Blender Foundation.
17  * All rights reserved.
18  */
19 
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "BLI_compiler_compat.h"
31 #include "BLI_listbase.h"
32 
33 #include "BKE_collision.h"
34 #include "BKE_effect.h"
35 #include "BKE_modifier.h"
36 
37 #include "DNA_collection_types.h"
38 #include "DNA_object_force_types.h"
39 #include "DNA_object_types.h"
40 
41 #include "DEG_depsgraph_build.h"
42 #include "DEG_depsgraph_physics.h"
43 #include "DEG_depsgraph_query.h"
44 
45 #include "depsgraph.h"
46 
47 namespace deg = blender::deg;
48 
49 /*************************** Evaluation Query API *****************************/
50 
51 static ePhysicsRelationType modifier_to_relation_type(unsigned int modifier_type)
52 {
53  switch (modifier_type) {
55  return DEG_PHYSICS_COLLISION;
60  }
61 
62  BLI_assert(!"Unknown collision modifier type");
64 }
65 /* Get ID from an ID type object, in a safe manner. This means that object can be nullptr,
66  * in which case the function returns nullptr.
67  */
68 template<class T> static ID *object_id_safe(T *object)
69 {
70  if (object == nullptr) {
71  return nullptr;
72  }
73  return &object->id;
74 }
75 
77 {
78  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
80  if (hash == nullptr) {
81  return nullptr;
82  }
83  /* Note: nullptr is a valid lookup key here as it means that the relation is not bound to a
84  * specific collection. */
85  ID *collection_orig = DEG_get_original_id(object_id_safe(collection));
86  return hash->lookup_default(collection_orig, nullptr);
87 }
88 
90  Collection *collection,
91  unsigned int modifier_type)
92 {
93  const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
96  if (hash == nullptr) {
97  return nullptr;
98  }
99  /* Note: nullptr is a valid lookup key here as it means that the relation is not bound to a
100  * specific collection. */
101  ID *collection_orig = DEG_get_original_id(object_id_safe(collection));
102  return hash->lookup_default(collection_orig, nullptr);
103 }
104 
105 /********************** Depsgraph Building API ************************/
106 
107 void DEG_add_collision_relations(DepsNodeHandle *handle,
108  Object *object,
109  Collection *collection,
110  unsigned int modifier_type,
111  DEG_CollobjFilterFunction filter_function,
112  const char *name)
113 {
115  deg::Depsgraph *deg_graph = (deg::Depsgraph *)depsgraph;
116  ListBase *relations = build_collision_relations(deg_graph, collection, modifier_type);
117  LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
118  Object *ob1 = relation->ob;
119  if (ob1 == object) {
120  continue;
121  }
122  if (filter_function == nullptr ||
123  filter_function(ob1, BKE_modifiers_findby_type(ob1, (ModifierType)modifier_type))) {
126  }
127  }
128 }
129 
130 void DEG_add_forcefield_relations(DepsNodeHandle *handle,
131  Object *object,
132  EffectorWeights *effector_weights,
133  bool add_absorption,
134  int skip_forcefield,
135  const char *name)
136 {
138  deg::Depsgraph *deg_graph = (deg::Depsgraph *)depsgraph;
139  ListBase *relations = build_effector_relations(deg_graph, effector_weights->group);
140  LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
141  if (relation->ob == object) {
142  continue;
143  }
144  if (relation->pd->forcefield == skip_forcefield) {
145  continue;
146  }
147 
148  /* Relation to forcefield object, optionally including geometry.
149  * Use special point cache relations for automatic cache clearing. */
150  DEG_add_object_pointcache_relation(handle, relation->ob, DEG_OB_COMP_TRANSFORM, name);
151 
152  if (relation->psys || ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
153  relation->pd->forcefield == PFIELD_GUIDE) {
154  /* TODO(sergey): Consider going more granular with more dedicated
155  * particle system operation. */
156  DEG_add_object_pointcache_relation(handle, relation->ob, DEG_OB_COMP_GEOMETRY, name);
157  }
158 
159  /* Smoke flow relations. */
160  if (relation->pd->forcefield == PFIELD_FLUIDFLOW && relation->pd->f_source != nullptr) {
162  handle, relation->pd->f_source, DEG_OB_COMP_TRANSFORM, "Fluid Force Domain");
164  handle, relation->pd->f_source, DEG_OB_COMP_GEOMETRY, "Fluid Force Domain");
165  }
166 
167  /* Absorption forces need collision relation. */
168  if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
170  handle, object, nullptr, eModifierType_Collision, nullptr, "Force Absorption");
171  }
172  }
173 }
174 
175 /******************************** Internal API ********************************/
176 
177 namespace blender::deg {
178 
180 {
182  if (hash == nullptr) {
185  }
186  /* If collection is nullptr still use it as a key.
187  * In this case the BKE_effector_relations_create() will create relates for all bases in the
188  * view layer.
189  */
190  ID *collection_id = object_id_safe(collection);
191  return hash->lookup_or_add_cb(collection_id, [&]() {
192  ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph);
194  });
195 }
196 
198  Collection *collection,
199  unsigned int modifier_type)
200 {
201  const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
203  if (hash == nullptr) {
206  }
207  /* If collection is nullptr still use it as a key.
208  * In this case the BKE_collision_relations_create() will create relates for all bases in the
209  * view layer.
210  */
211  ID *collection_id = object_id_safe(collection);
212  return hash->lookup_or_add_cb(collection_id, [&]() {
213  ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph);
214  return BKE_collision_relations_create(depsgraph, collection, modifier_type);
215  });
216 }
217 
219 {
220  for (int i = 0; i < DEG_PHYSICS_RELATIONS_NUM; i++) {
222  if (hash) {
224 
225  switch (type) {
227  for (ListBase *list : hash->values()) {
229  }
230  break;
234  for (ListBase *list : hash->values()) {
236  }
237  break;
239  break;
240  }
241  delete hash;
242  graph->physics_relations[i] = nullptr;
243  }
244  }
245 }
246 
247 } // namespace blender::deg
struct ListBase * BKE_collision_relations_create(struct Depsgraph *depsgraph, struct Collection *collection, unsigned int modifier_type)
Definition: collision.c:1267
void BKE_collision_relations_free(struct ListBase *relations)
Definition: collision.c:1287
struct ListBase * BKE_effector_relations_create(struct Depsgraph *depsgraph, struct ViewLayer *view_layer, struct Collection *collection)
Definition: effect.c:227
void BKE_effector_relations_free(struct ListBase *lb)
Definition: effect.c:265
struct ModifierData * BKE_modifiers_findby_type(const struct Object *ob, ModifierType type)
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
void DEG_add_object_pointcache_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
struct Depsgraph * DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle)
ePhysicsRelationType
@ DEG_PHYSICS_DYNAMIC_BRUSH
@ DEG_PHYSICS_SMOKE_COLLISION
@ DEG_PHYSICS_COLLISION
@ DEG_PHYSICS_RELATIONS_NUM
@ DEG_PHYSICS_EFFECTOR
bool(* DEG_CollobjFilterFunction)(struct Object *obj, struct ModifierData *md)
struct ID * DEG_get_original_id(struct ID *id)
Object groups, one object can be in many groups at once.
ModifierType
@ eModifierType_Fluid
@ eModifierType_Collision
@ eModifierType_DynamicPaint
#define PFIELD_SHAPE_SURFACE
#define PFIELD_VISIBILITY
@ PFIELD_FLUIDFLOW
@ PFIELD_GUIDE
#define PFIELD_SHAPE_POINTS
Object is a sort of wrapper for general info.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
Depsgraph * graph
const Depsgraph * depsgraph
ListBase * DEG_get_collision_relations(const Depsgraph *graph, Collection *collection, unsigned int modifier_type)
static ID * object_id_safe(T *object)
void DEG_add_collision_relations(DepsNodeHandle *handle, Object *object, Collection *collection, unsigned int modifier_type, DEG_CollobjFilterFunction filter_function, const char *name)
void DEG_add_forcefield_relations(DepsNodeHandle *handle, Object *object, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
static ePhysicsRelationType modifier_to_relation_type(unsigned int modifier_type)
ListBase * DEG_get_effector_relations(const Depsgraph *graph, Collection *collection)
#define T
ListBase * build_collision_relations(Depsgraph *graph, Collection *collection, unsigned int modifier_type)
ListBase * build_effector_relations(Depsgraph *graph, Collection *collection)
void clear_physics_relations(Depsgraph *graph)
#define hash
Definition: noise.c:169
struct Collection * group
Definition: DNA_ID.h:273
Map< const ID *, ListBase * > * physics_relations[DEG_PHYSICS_RELATIONS_NUM]
Definition: depsgraph.h:169
ViewLayer * view_layer
Definition: depsgraph.h:135