Cleanup: remove redundant doxygen \file argument
[blender.git] / source / blender / depsgraph / intern / depsgraph_physics.cc
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
20 /** \file \ingroup depsgraph
21  *
22  * Physics utilities for effectors and collision.
23  */
24
25 #include "intern/depsgraph_physics.h"
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_compiler_compat.h"
30 #include "BLI_ghash.h"
31 #include "BLI_listbase.h"
32
33 extern "C" {
34 #include "BKE_collision.h"
35 #include "BKE_effect.h"
36 #include "BKE_modifier.h"
37 } /* extern "C" */
38
39 #include "DNA_collection_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_object_force_types.h"
42
43 #include "DEG_depsgraph_build.h"
44 #include "DEG_depsgraph_physics.h"
45 #include "DEG_depsgraph_query.h"
46
47 #include "depsgraph.h"
48
49 /*************************** Evaluation Query API *****************************/
50
51 static ePhysicsRelationType modifier_to_relation_type(
52         unsigned int modifier_type)
53 {
54         switch (modifier_type) {
55                 case eModifierType_Collision:
56                         return DEG_PHYSICS_COLLISION;
57                 case eModifierType_Smoke:
58                         return DEG_PHYSICS_SMOKE_COLLISION;
59                 case eModifierType_DynamicPaint:
60                         return DEG_PHYSICS_DYNAMIC_BRUSH;
61         }
62
63         BLI_assert(!"Unknown collision modifier type");
64         return DEG_PHYSICS_RELATIONS_NUM;
65 }
66
67 ListBase *DEG_get_effector_relations(const Depsgraph *graph,
68                                      Collection *collection)
69 {
70         const DEG::Depsgraph *deg_graph =
71                 reinterpret_cast<const DEG::Depsgraph *>(graph);
72         if (deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR] == NULL) {
73                 return NULL;
74         }
75
76         ID *collection_orig = DEG_get_original_id(&collection->id);
77         return (ListBase *)BLI_ghash_lookup(
78                 deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR],
79                 collection_orig);
80 }
81
82 ListBase *DEG_get_collision_relations(const Depsgraph *graph,
83                                       Collection *collection,
84                                       unsigned int modifier_type)
85 {
86         const DEG::Depsgraph *deg_graph =
87                 reinterpret_cast<const DEG::Depsgraph *>(graph);
88         const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
89         if (deg_graph->physics_relations[type] == NULL) {
90                 return NULL;
91         }
92         ID *collection_orig = DEG_get_original_id(&collection->id);
93         return (ListBase *)BLI_ghash_lookup(
94                 deg_graph->physics_relations[type],
95                 collection_orig);
96 }
97
98 /********************** Depsgraph Building API ************************/
99
100 void DEG_add_collision_relations(DepsNodeHandle *handle,
101                                  Object *object,
102                                  Collection *collection,
103                                  unsigned int modifier_type,
104                                  DEG_CollobjFilterFunction filter_function,
105                                  const char *name)
106 {
107         Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
108         DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)depsgraph;
109         ListBase *relations = build_collision_relations(
110                 deg_graph, collection, modifier_type);
111         LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
112                 Object *ob1 = relation->ob;
113                 if (ob1 == object) {
114                         continue;
115                 }
116                 if (filter_function == NULL ||
117                     filter_function(
118                             ob1,
119                             modifiers_findByType(ob1, (ModifierType)modifier_type)))
120                 {
121                         DEG_add_object_pointcache_relation(
122                                 handle, ob1, DEG_OB_COMP_TRANSFORM, name);
123                         DEG_add_object_pointcache_relation(
124                                 handle, ob1, DEG_OB_COMP_GEOMETRY, name);
125                 }
126         }
127 }
128
129 void DEG_add_forcefield_relations(DepsNodeHandle *handle,
130                                   Object *object,
131                                   EffectorWeights *effector_weights,
132                                   bool add_absorption,
133                                   int skip_forcefield,
134                                   const char *name)
135 {
136         Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
137         DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)depsgraph;
138         ListBase *relations =
139                 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(
151                         handle, relation->ob, DEG_OB_COMP_TRANSFORM, name);
152
153                 if (relation->psys ||
154                     ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
155                     relation->pd->forcefield == PFIELD_GUIDE)
156                 {
157                         /* TODO(sergey): Consider going more granular with more dedicated
158                          * particle system operation. */
159                         DEG_add_object_pointcache_relation(
160                                 handle, relation->ob, DEG_OB_COMP_GEOMETRY, name);
161                 }
162
163                 /* Smoke flow relations. */
164                 if (relation->pd->forcefield == PFIELD_SMOKEFLOW &&
165                     relation->pd->f_source != NULL)
166                 {
167                         DEG_add_object_pointcache_relation(handle,
168                                                            relation->pd->f_source,
169                                                            DEG_OB_COMP_TRANSFORM,
170                                                            "Smoke Force Domain");
171                         DEG_add_object_pointcache_relation(handle,
172                                                            relation->pd->f_source,
173                                                            DEG_OB_COMP_GEOMETRY,
174                                                            "Smoke Force Domain");
175                 }
176
177                 /* Absorption forces need collision relation. */
178                 if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
179                         DEG_add_collision_relations(handle,
180                                                     object,
181                                                     NULL,
182                                                     eModifierType_Collision,
183                                                     NULL,
184                                                     "Force Absorption");
185                 }
186         }
187 }
188
189 /******************************** Internal API ********************************/
190
191 namespace DEG
192 {
193
194 ListBase *build_effector_relations(Depsgraph *graph, Collection *collection)
195 {
196         GHash *hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR];
197         if (hash == NULL) {
198                 graph->physics_relations[DEG_PHYSICS_EFFECTOR] =
199                         BLI_ghash_ptr_new("Depsgraph physics relations hash");
200                 hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR];
201         }
202         ListBase *relations =
203                 reinterpret_cast<ListBase*>(BLI_ghash_lookup(hash, collection));
204         if (relations == NULL) {
205                 ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph*>(graph);
206                 relations = BKE_effector_relations_create(
207                         depsgraph, graph->view_layer, collection);
208                 BLI_ghash_insert(hash, &collection->id, relations);
209         }
210         return relations;
211 }
212
213 ListBase *build_collision_relations(Depsgraph *graph,
214                                     Collection *collection,
215                                     unsigned int modifier_type)
216 {
217         const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
218         GHash *hash = graph->physics_relations[type];
219         if (hash == NULL) {
220                 graph->physics_relations[type] =
221                         BLI_ghash_ptr_new("Depsgraph physics relations hash");
222                 hash = graph->physics_relations[type];
223         }
224         ListBase *relations =
225                 reinterpret_cast<ListBase*>(BLI_ghash_lookup(hash, collection));
226         if (relations == NULL) {
227                 ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph*>(graph);
228                 relations = BKE_collision_relations_create(
229                         depsgraph, collection, modifier_type);
230                 BLI_ghash_insert(hash, &collection->id, relations);
231         }
232         return relations;
233 }
234
235 namespace {
236
237 void free_effector_relations(void *value)
238 {
239         BKE_effector_relations_free(reinterpret_cast<ListBase*>(value));
240 }
241
242 void free_collision_relations(void *value)
243 {
244         BKE_collision_relations_free(reinterpret_cast<ListBase*>(value));
245 }
246
247 }  // namespace
248
249 void clear_physics_relations(Depsgraph *graph)
250 {
251         for (int i = 0; i < DEG_PHYSICS_RELATIONS_NUM; i++) {
252                 if (graph->physics_relations[i]) {
253                         const ePhysicsRelationType type = (ePhysicsRelationType)i;
254
255                         switch (type) {
256                                 case DEG_PHYSICS_EFFECTOR:
257                                         BLI_ghash_free(graph->physics_relations[i],
258                                                        NULL,
259                                                        free_effector_relations);
260                                         break;
261                                 case DEG_PHYSICS_COLLISION:
262                                 case DEG_PHYSICS_SMOKE_COLLISION:
263                                 case DEG_PHYSICS_DYNAMIC_BRUSH:
264                                         BLI_ghash_free(graph->physics_relations[i],
265                                                        NULL,
266                                                        free_collision_relations);
267                                         break;
268                                 case DEG_PHYSICS_RELATIONS_NUM:
269                                         break;
270                         }
271                         graph->physics_relations[i] = NULL;
272                 }
273         }
274 }
275
276 }