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