split BKE_utildefines.h, now it only has blender specific defines like GS() MAKE_ID...
[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 #include "DNA_scene_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_meshdata_types.h"
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_math.h"
40 #include "BLI_utildefines.h"
41
42 #include "BKE_utildefines.h"
43 #include "BKE_collision.h"
44 #include "BKE_cdderivedmesh.h"
45 #include "BKE_global.h"
46 #include "BKE_modifier.h"
47 #include "BKE_object.h"
48 #include "BKE_pointcache.h"
49 #include "BKE_scene.h"
50
51
52 static void initData(ModifierData *md) 
53 {
54         CollisionModifierData *collmd = (CollisionModifierData*) md;
55         
56         collmd->x = NULL;
57         collmd->xnew = NULL;
58         collmd->current_x = NULL;
59         collmd->current_xnew = NULL;
60         collmd->current_v = NULL;
61         collmd->time = -1000;
62         collmd->numverts = 0;
63         collmd->bvhtree = NULL;
64 }
65
66 static void freeData(ModifierData *md)
67 {
68         CollisionModifierData *collmd = (CollisionModifierData*) md;
69         
70         if (collmd) 
71         {
72                 if(collmd->bvhtree)
73                         BLI_bvhtree_free(collmd->bvhtree);
74                 if(collmd->x)
75                         MEM_freeN(collmd->x);
76                 if(collmd->xnew)
77                         MEM_freeN(collmd->xnew);
78                 if(collmd->current_x)
79                         MEM_freeN(collmd->current_x);
80                 if(collmd->current_xnew)
81                         MEM_freeN(collmd->current_xnew);
82                 if(collmd->current_v)
83                         MEM_freeN(collmd->current_v);
84                 if(collmd->mfaces)
85                         MEM_freeN(collmd->mfaces);
86                 
87                 collmd->x = NULL;
88                 collmd->xnew = NULL;
89                 collmd->current_x = NULL;
90                 collmd->current_xnew = NULL;
91                 collmd->current_v = NULL;
92                 collmd->time = -1000;
93                 collmd->numverts = 0;
94                 collmd->bvhtree = NULL;
95                 collmd->mfaces = NULL;
96         }
97 }
98
99 static int dependsOnTime(ModifierData *UNUSED(md))
100 {
101         return 1;
102 }
103
104 static void deformVerts(ModifierData *md, Object *ob,
105                                                 DerivedMesh *derivedData,
106                                                 float (*vertexCos)[3],
107                                                 int UNUSED(numVerts),
108                                                 int UNUSED(useRenderParams),
109                                                 int UNUSED(isFinalCalc))
110 {
111         CollisionModifierData *collmd = (CollisionModifierData*) md;
112         DerivedMesh *dm = NULL;
113         float current_time = 0;
114         unsigned int numverts = 0, i = 0;
115         MVert *tempVert = NULL;
116         
117         /* if possible use/create DerivedMesh */
118         if(derivedData) dm = CDDM_copy(derivedData);
119         else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
120         
121         if(!ob->pd)
122         {
123                 printf("CollisionModifier deformVerts: Should not happen!\n");
124                 return;
125         }
126         
127         if(dm)
128         {
129                 CDDM_apply_vert_coords(dm, vertexCos);
130                 CDDM_calc_normals(dm);
131                 
132                 current_time = BKE_curframe(md->scene);
133                 
134                 if(G.rt > 0)
135                         printf("current_time %f, collmd->time %f\n", current_time, collmd->time);
136                 
137                 numverts = dm->getNumVerts ( dm );
138                 
139                 if((current_time > collmd->time)|| (BKE_ptcache_get_continue_physics()))
140                 {       
141                         // check if mesh has changed
142                         if(collmd->x && (numverts != collmd->numverts))
143                                 freeData((ModifierData *)collmd);
144                         
145                         if(collmd->time == -1000) // first time
146                         {
147                                 collmd->x = dm->dupVertArray(dm); // frame start position
148                                 
149                                 for ( i = 0; i < numverts; i++ )
150                                 {
151                                         // we save global positions
152                                         mul_m4_v3( ob->obmat, collmd->x[i].co );
153                                 }
154                                 
155                                 collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
156                                 collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
157                                 collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
158                                 collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
159
160                                 collmd->numverts = numverts;
161                                 
162                                 collmd->mfaces = dm->dupFaceArray(dm);
163                                 collmd->numfaces = dm->getNumFaces(dm);
164                                 
165                                 // create bounding box hierarchy
166                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
167                                 
168                                 collmd->time = current_time;
169                         }
170                         else if(numverts == collmd->numverts)
171                         {
172                                 // put positions to old positions
173                                 tempVert = collmd->x;
174                                 collmd->x = collmd->xnew;
175                                 collmd->xnew = tempVert;
176                                 
177                                 memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
178                                 
179                                 for ( i = 0; i < numverts; i++ )
180                                 {
181                                         // we save global positions
182                                         mul_m4_v3( ob->obmat, collmd->xnew[i].co );
183                                 }
184                                 
185                                 memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert));
186                                 memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
187                                 
188                                 /* check if GUI setting has changed for bvh */
189                                 if(collmd->bvhtree) 
190                                 {
191                                         if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree))
192                                         {
193                                                 BLI_bvhtree_free(collmd->bvhtree);
194                                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
195                                         }
196                         
197                                 }
198                                 
199                                 /* happens on file load (ONLY when i decomment changes in readfile.c) */
200                                 if(!collmd->bvhtree)
201                                 {
202                                         collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
203                                 }
204                                 else
205                                 {
206                                         // recalc static bounding boxes
207                                         bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
208                                 }
209                                 
210                                 collmd->time = current_time;
211                         }
212                         else if(numverts != collmd->numverts)
213                         {
214                                 freeData((ModifierData *)collmd);
215                         }
216                         
217                 }
218                 else if(current_time < collmd->time)
219                 {       
220                         freeData((ModifierData *)collmd);
221                 }
222                 else
223                 {
224                         if(numverts != collmd->numverts)
225                         {
226                                 freeData((ModifierData *)collmd);
227                         }
228                 }
229         }
230         
231         if(dm)
232                 dm->release(dm);
233 }
234
235
236 ModifierTypeInfo modifierType_Collision = {
237         /* name */              "Collision",
238         /* structName */        "CollisionModifierData",
239         /* structSize */        sizeof(CollisionModifierData),
240         /* type */              eModifierTypeType_OnlyDeform,
241         /* flags */             eModifierTypeFlag_AcceptsMesh
242                                                         | eModifierTypeFlag_Single,
243
244         /* copyData */          0,
245         /* deformVerts */       deformVerts,
246         /* deformVertsEM */     0,
247         /* deformMatricesEM */  0,
248         /* applyModifier */     0,
249         /* applyModifierEM */   0,
250         /* initData */          initData,
251         /* requiredDataMask */  0,
252         /* freeData */          freeData,
253         /* isDisabled */        0,
254         /* updateDepgraph */    0,
255         /* dependsOnTime */     dependsOnTime,
256         /* dependsOnNormals */  0,
257         /* foreachObjectLink */ 0,
258         /* foreachIDLink */     0,
259 };