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