Depsgraph: New dependency graph integration commit
[blender.git] / source / blender / modifiers / intern / MOD_collision.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software  Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Dunbar
22  *                 Ton Roosendaal,
23  *                 Ben Batt,
24  *                 Brecht Van Lommel,
25  *                 Campbell Barton
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  */
30
31 /** \file blender/modifiers/intern/MOD_collision.c
32  *  \ingroup modifiers
33  */
34
35 #include "DNA_object_types.h"
36 #include "DNA_meshdata_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_math.h"
41 #include "BLI_utildefines.h"
42
43
44 #include "BKE_collision.h"
45 #include "BKE_cdderivedmesh.h"
46 #include "BKE_global.h"
47 #include "BKE_modifier.h"
48 #include "BKE_pointcache.h"
49 #include "BKE_scene.h"
50
51 static void initData(ModifierData *md) 
52 {
53         CollisionModifierData *collmd = (CollisionModifierData *) md;
54         
55         collmd->x = NULL;
56         collmd->xnew = NULL;
57         collmd->current_x = NULL;
58         collmd->current_xnew = NULL;
59         collmd->current_v = NULL;
60         collmd->time_x = collmd->time_xnew = -1000;
61         collmd->numverts = 0;
62         collmd->bvhtree = NULL;
63 }
64
65 static void freeData(ModifierData *md)
66 {
67         CollisionModifierData *collmd = (CollisionModifierData *) md;
68         
69         if (collmd) {
70                 if (collmd->bvhtree)
71                         BLI_bvhtree_free(collmd->bvhtree);
72                 if (collmd->x)
73                         MEM_freeN(collmd->x);
74                 if (collmd->xnew)
75                         MEM_freeN(collmd->xnew);
76                 if (collmd->current_x)
77                         MEM_freeN(collmd->current_x);
78                 if (collmd->current_xnew)
79                         MEM_freeN(collmd->current_xnew);
80                 if (collmd->current_v)
81                         MEM_freeN(collmd->current_v);
82                 if (collmd->mfaces)
83                         MEM_freeN(collmd->mfaces);
84                 
85                 collmd->x = NULL;
86                 collmd->xnew = NULL;
87                 collmd->current_x = NULL;
88                 collmd->current_xnew = NULL;
89                 collmd->current_v = NULL;
90                 collmd->time_x = collmd->time_xnew = -1000;
91                 collmd->numverts = 0;
92                 collmd->bvhtree = NULL;
93                 collmd->mfaces = NULL;
94         }
95 }
96
97 static bool dependsOnTime(ModifierData *UNUSED(md))
98 {
99         return true;
100 }
101
102 static void deformVerts(ModifierData *md, Object *ob,
103                         DerivedMesh *derivedData,
104                         float (*vertexCos)[3],
105                         int UNUSED(numVerts),
106                         ModifierApplyFlag UNUSED(flag))
107 {
108         CollisionModifierData *collmd = (CollisionModifierData *) md;
109         DerivedMesh *dm = NULL;
110         MVert *tempVert = NULL;
111         
112         /* if possible use/create DerivedMesh */
113         if (derivedData) dm = CDDM_copy(derivedData);
114         else if (ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data);
115         
116         if (!ob->pd) {
117                 printf("CollisionModifier deformVerts: Should not happen!\n");
118                 return;
119         }
120         
121         if (dm) {
122                 float current_time = 0;
123                 unsigned int numverts = 0;
124
125                 CDDM_apply_vert_coords(dm, vertexCos);
126                 CDDM_calc_normals(dm);
127                 
128                 current_time = BKE_scene_frame_get(md->scene);
129                 
130                 if (G.debug_value > 0)
131                         printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew);
132                 
133                 numverts = dm->getNumVerts(dm);
134                 
135                 if (current_time > collmd->time_xnew) {
136                         unsigned int i;
137
138                         /* check if mesh has changed */
139                         if (collmd->x && (numverts != collmd->numverts))
140                                 freeData((ModifierData *)collmd);
141
142                         if (collmd->time_xnew == -1000) { /* first time */
143                                 collmd->x = dm->dupVertArray(dm); /* frame start position */
144
145                                 for (i = 0; i < numverts; i++) {
146                                         /* we save global positions */
147                                         mul_m4_v3(ob->obmat, collmd->x[i].co);
148                                 }
149                                 
150                                 collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
151                                 collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
152                                 collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
153                                 collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
154
155                                 collmd->numverts = numverts;
156                                 
157                                 DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
158
159                                 collmd->mfaces = dm->dupTessFaceArray(dm);
160                                 collmd->numfaces = dm->getNumTessFaces(dm);
161                                 
162                                 /* create bounding box hierarchy */
163                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
164
165                                 collmd->time_x = collmd->time_xnew = current_time;
166                         }
167                         else if (numverts == collmd->numverts) {
168                                 /* put positions to old positions */
169                                 tempVert = collmd->x;
170                                 collmd->x = collmd->xnew;
171                                 collmd->xnew = tempVert;
172                                 collmd->time_x = collmd->time_xnew;
173
174                                 memcpy(collmd->xnew, dm->getVertArray(dm), numverts * sizeof(MVert));
175
176                                 for (i = 0; i < numverts; i++) {
177                                         /* we save global positions */
178                                         mul_m4_v3(ob->obmat, collmd->xnew[i].co);
179                                 }
180                                 
181                                 memcpy(collmd->current_xnew, collmd->x, numverts * sizeof(MVert));
182                                 memcpy(collmd->current_x, collmd->x, numverts * sizeof(MVert));
183                                 
184                                 /* check if GUI setting has changed for bvh */
185                                 if (collmd->bvhtree) {
186                                         if (ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree)) {
187                                                 BLI_bvhtree_free(collmd->bvhtree);
188                                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
189                                         }
190                         
191                                 }
192                                 
193                                 /* happens on file load (ONLY when i decomment changes in readfile.c) */
194                                 if (!collmd->bvhtree) {
195                                         collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
196                                 }
197                                 else {
198                                         /* recalc static bounding boxes */
199                                         bvhtree_update_from_mvert(collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1);
200                                 }
201                                 
202                                 collmd->time_xnew = current_time;
203                         }
204                         else if (numverts != collmd->numverts) {
205                                 freeData((ModifierData *)collmd);
206                         }
207                         
208                 }
209                 else if (current_time < collmd->time_xnew) {
210                         freeData((ModifierData *)collmd);
211                 }
212                 else {
213                         if (numverts != collmd->numverts) {
214                                 freeData((ModifierData *)collmd);
215                         }
216                 }
217         }
218         
219         if (dm)
220                 dm->release(dm);
221 }
222
223
224 ModifierTypeInfo modifierType_Collision = {
225         /* name */              "Collision",
226         /* structName */        "CollisionModifierData",
227         /* structSize */        sizeof(CollisionModifierData),
228         /* type */              eModifierTypeType_OnlyDeform,
229         /* flags */             eModifierTypeFlag_AcceptsMesh |
230                                 eModifierTypeFlag_Single,
231
232         /* copyData */          NULL,
233         /* deformVerts */       deformVerts,
234         /* deformMatrices */    NULL,
235         /* deformVertsEM */     NULL,
236         /* deformMatricesEM */  NULL,
237         /* applyModifier */     NULL,
238         /* applyModifierEM */   NULL,
239         /* initData */          initData,
240         /* requiredDataMask */  NULL,
241         /* freeData */          freeData,
242         /* isDisabled */        NULL,
243         /* updateDepgraph */    NULL,
244         /* updateDepsgraph */   NULL,
245         /* dependsOnTime */     dependsOnTime,
246         /* dependsOnNormals */  NULL,
247         /* foreachObjectLink */ NULL,
248         /* foreachIDLink */     NULL,
249         /* foreachTexLink */    NULL,
250 };