Depsgraph: Add utility function for transform dependency
[blender.git] / source / blender / modifiers / intern / MOD_cloth.c
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) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file \ingroup modifiers
21  */
22
23 #include <string.h>
24
25 #include "DNA_cloth_types.h"
26 #include "DNA_key_types.h"
27 #include "DNA_mesh_types.h"
28 #include "DNA_scene_types.h"
29 #include "DNA_object_types.h"
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_listbase.h"
34 #include "BLI_utildefines.h"
35
36 #include "BKE_cloth.h"
37 #include "BKE_effect.h"
38 #include "BKE_global.h"
39 #include "BKE_key.h"
40 #include "BKE_library.h"
41 #include "BKE_library_query.h"
42 #include "BKE_mesh.h"
43 #include "BKE_modifier.h"
44 #include "BKE_pointcache.h"
45
46 #include "DEG_depsgraph_physics.h"
47 #include "DEG_depsgraph_query.h"
48
49 #include "MOD_util.h"
50
51 static void initData(ModifierData *md)
52 {
53         ClothModifierData *clmd = (ClothModifierData *) md;
54
55         clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms");
56         clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms");
57         clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches);
58
59         /* check for alloc failing */
60         if (!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache)
61                 return;
62
63         cloth_init(clmd);
64 }
65
66 static void deformVerts(
67         ModifierData *md, const ModifierEvalContext *ctx,
68         Mesh *mesh, float (*vertexCos)[3],
69         int numVerts)
70 {
71         Mesh *mesh_src;
72         ClothModifierData *clmd = (ClothModifierData *) md;
73         Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
74
75         /* check for alloc failing */
76         if (!clmd->sim_parms || !clmd->coll_parms) {
77                 initData(md);
78
79                 if (!clmd->sim_parms || !clmd->coll_parms)
80                         return;
81         }
82
83         if (mesh == NULL) {
84                 mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, numVerts, false, false);
85         }
86         else {
87                 /* Not possible to use get_mesh() in this case as we'll modify its vertices
88                  * and get_mesh() would return 'mesh' directly. */
89                 BKE_id_copy_ex(NULL, (ID *)mesh, (ID **)&mesh_src, LIB_ID_COPY_LOCALIZE);
90         }
91
92         /* TODO(sergey): For now it actually duplicates logic from DerivedMesh.c
93          * and needs some more generic solution. But starting experimenting with
94          * this so close to the release is not that nice..
95          *
96          * Also hopefully new cloth system will arrive soon..
97          */
98         if (mesh == NULL && clmd->sim_parms->shapekey_rest) {
99                 KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ctx->object),
100                                                      clmd->sim_parms->shapekey_rest);
101                 if (kb && kb->data != NULL) {
102                         float (*layerorco)[3];
103                         if (!(layerorco = CustomData_get_layer(&mesh_src->vdata, CD_CLOTH_ORCO))) {
104                                 layerorco = CustomData_add_layer(&mesh_src->vdata, CD_CLOTH_ORCO, CD_CALLOC, NULL, mesh_src->totvert);
105                         }
106
107                         memcpy(layerorco, kb->data, sizeof(float) * 3 * numVerts);
108                 }
109         }
110
111         BKE_mesh_apply_vert_coords(mesh_src, vertexCos);
112
113         clothModifier_do(clmd, ctx->depsgraph, scene, ctx->object, mesh_src, vertexCos);
114
115         BKE_id_free(NULL, mesh_src);
116 }
117
118 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
119 {
120         ClothModifierData *clmd = (ClothModifierData *)md;
121         if (clmd != NULL) {
122                 DEG_add_collision_relations(ctx->node, ctx->object, clmd->coll_parms->group, eModifierType_Collision, NULL, "Cloth Collision");
123                 DEG_add_forcefield_relations(ctx->node, ctx->object, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
124         }
125         DEG_add_modifier_to_transform_relation(ctx->node, "Cloth Modifier");
126 }
127
128 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
129 {
130         CustomDataMask dataMask = 0;
131         ClothModifierData *clmd = (ClothModifierData *)md;
132
133         if (cloth_uses_vgroup(clmd))
134                 dataMask |= CD_MASK_MDEFORMVERT;
135
136         if (clmd->sim_parms->shapekey_rest != 0)
137                 dataMask |= CD_MASK_CLOTH_ORCO;
138
139         return dataMask;
140 }
141
142 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
143 {
144         const ClothModifierData *clmd = (const ClothModifierData *) md;
145         ClothModifierData *tclmd = (ClothModifierData *) target;
146
147         if (tclmd->sim_parms) {
148                 if (tclmd->sim_parms->effector_weights)
149                         MEM_freeN(tclmd->sim_parms->effector_weights);
150                 MEM_freeN(tclmd->sim_parms);
151         }
152
153         if (tclmd->coll_parms)
154                 MEM_freeN(tclmd->coll_parms);
155
156         BKE_ptcache_free_list(&tclmd->ptcaches);
157         if (flag & LIB_ID_CREATE_NO_MAIN) {
158                 /* Share the cache with the original object's modifier. */
159                 tclmd->modifier.flag |= eModifierFlag_SharedCaches;
160                 tclmd->ptcaches = clmd->ptcaches;
161                 tclmd->point_cache = clmd->point_cache;
162         }
163         else {
164                 tclmd->point_cache = BKE_ptcache_add(&tclmd->ptcaches);
165                 tclmd->point_cache->step = 1;
166         }
167
168         tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms);
169         if (clmd->sim_parms->effector_weights)
170                 tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights);
171         tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
172         tclmd->clothObject = NULL;
173         tclmd->hairdata = NULL;
174         tclmd->solver_result = NULL;
175 }
176
177 static bool dependsOnTime(ModifierData *UNUSED(md))
178 {
179         return true;
180 }
181
182 static void freeData(ModifierData *md)
183 {
184         ClothModifierData *clmd = (ClothModifierData *) md;
185
186         if (clmd) {
187                 if (G.debug & G_DEBUG_SIMDATA) {
188                         printf("clothModifier_freeData\n");
189                 }
190
191                 cloth_free_modifier_extern(clmd);
192
193                 if (clmd->sim_parms) {
194                         if (clmd->sim_parms->effector_weights)
195                                 MEM_freeN(clmd->sim_parms->effector_weights);
196                         MEM_freeN(clmd->sim_parms);
197                 }
198                 if (clmd->coll_parms)
199                         MEM_freeN(clmd->coll_parms);
200
201                 if (md->flag & eModifierFlag_SharedCaches) {
202                         BLI_listbase_clear(&clmd->ptcaches);
203                 }
204                 else {
205                         BKE_ptcache_free_list(&clmd->ptcaches);
206                 }
207                 clmd->point_cache = NULL;
208
209                 if (clmd->hairdata)
210                         MEM_freeN(clmd->hairdata);
211
212                 if (clmd->solver_result)
213                         MEM_freeN(clmd->solver_result);
214         }
215 }
216
217 static void foreachIDLink(
218         ModifierData *md, Object *ob,
219         IDWalkFunc walk, void *userData)
220 {
221         ClothModifierData *clmd = (ClothModifierData *) md;
222
223         if (clmd->coll_parms) {
224                 walk(userData, ob, (ID **)&clmd->coll_parms->group, IDWALK_CB_NOP);
225         }
226
227         if (clmd->sim_parms && clmd->sim_parms->effector_weights) {
228                 walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_CB_NOP);
229         }
230 }
231
232 ModifierTypeInfo modifierType_Cloth = {
233         /* name */              "Cloth",
234         /* structName */        "ClothModifierData",
235         /* structSize */        sizeof(ClothModifierData),
236         /* type */              eModifierTypeType_OnlyDeform,
237         /* flags */             eModifierTypeFlag_AcceptsMesh |
238                                 eModifierTypeFlag_UsesPointCache |
239                                 eModifierTypeFlag_Single,
240
241         /* copyData */          copyData,
242
243         /* deformVerts_DM */    NULL,
244         /* deformMatrices_DM */ NULL,
245         /* deformVertsEM_DM */  NULL,
246         /* deformMatricesEM_DM*/NULL,
247         /* applyModifier_DM */  NULL,
248
249         /* deformVerts */       deformVerts,
250         /* deformMatrices */    NULL,
251         /* deformVertsEM */     NULL,
252         /* deformMatricesEM */  NULL,
253         /* applyModifier */     NULL,
254
255         /* initData */          initData,
256         /* requiredDataMask */  requiredDataMask,
257         /* freeData */          freeData,
258         /* isDisabled */        NULL,
259         /* updateDepsgraph */   updateDepsgraph,
260         /* dependsOnTime */     dependsOnTime,
261         /* dependsOnNormals */  NULL,
262         /* foreachObjectLink */ NULL,
263         /* foreachIDLink */     foreachIDLink,
264         /* foreachTexLink */    NULL,
265 };