enforce string limits (reported by pedantic checking tools & some developers).
[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
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         MVert *tempVert = NULL;
114         
115         /* if possible use/create DerivedMesh */
116         if(derivedData) dm = CDDM_copy(derivedData);
117         else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
118         
119         if(!ob->pd)
120         {
121                 printf("CollisionModifier deformVerts: Should not happen!\n");
122                 return;
123         }
124         
125         if(dm)
126         {
127                 float current_time = 0;
128                 unsigned int numverts = 0;
129
130                 CDDM_apply_vert_coords(dm, vertexCos);
131                 CDDM_calc_normals(dm);
132                 
133                 current_time = BKE_curframe(md->scene);
134                 
135                 if(G.rt > 0)
136                         printf("current_time %f, collmd->time %f\n", current_time, collmd->time);
137                 
138                 numverts = dm->getNumVerts ( dm );
139                 
140                 if((current_time > collmd->time)|| (BKE_ptcache_get_continue_physics()))
141                 {
142                         unsigned int i;
143
144                         // check if mesh has changed
145                         if(collmd->x && (numverts != collmd->numverts))
146                                 freeData((ModifierData *)collmd);
147                         
148                         if(collmd->time == -1000) // first time
149                         {
150                                 collmd->x = dm->dupVertArray(dm); // frame start position
151                                 
152                                 for ( i = 0; i < numverts; i++ )
153                                 {
154                                         // we save global positions
155                                         mul_m4_v3( ob->obmat, collmd->x[i].co );
156                                 }
157                                 
158                                 collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
159                                 collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
160                                 collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
161                                 collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
162
163                                 collmd->numverts = numverts;
164                                 
165                                 collmd->mfaces = dm->dupFaceArray(dm);
166                                 collmd->numfaces = dm->getNumFaces(dm);
167                                 
168                                 // create bounding box hierarchy
169                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
170                                 
171                                 collmd->time = current_time;
172                         }
173                         else if(numverts == collmd->numverts)
174                         {
175                                 // put positions to old positions
176                                 tempVert = collmd->x;
177                                 collmd->x = collmd->xnew;
178                                 collmd->xnew = tempVert;
179                                 
180                                 memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
181                                 
182                                 for ( i = 0; i < numverts; i++ )
183                                 {
184                                         // we save global positions
185                                         mul_m4_v3( ob->obmat, collmd->xnew[i].co );
186                                 }
187                                 
188                                 memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert));
189                                 memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
190                                 
191                                 /* check if GUI setting has changed for bvh */
192                                 if(collmd->bvhtree) 
193                                 {
194                                         if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree))
195                                         {
196                                                 BLI_bvhtree_free(collmd->bvhtree);
197                                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
198                                         }
199                         
200                                 }
201                                 
202                                 /* happens on file load (ONLY when i decomment changes in readfile.c) */
203                                 if(!collmd->bvhtree)
204                                 {
205                                         collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
206                                 }
207                                 else
208                                 {
209                                         // recalc static bounding boxes
210                                         bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
211                                 }
212                                 
213                                 collmd->time = current_time;
214                         }
215                         else if(numverts != collmd->numverts)
216                         {
217                                 freeData((ModifierData *)collmd);
218                         }
219                         
220                 }
221                 else if(current_time < collmd->time)
222                 {       
223                         freeData((ModifierData *)collmd);
224                 }
225                 else
226                 {
227                         if(numverts != collmd->numverts)
228                         {
229                                 freeData((ModifierData *)collmd);
230                         }
231                 }
232         }
233         
234         if(dm)
235                 dm->release(dm);
236 }
237
238
239 ModifierTypeInfo modifierType_Collision = {
240         /* name */              "Collision",
241         /* structName */        "CollisionModifierData",
242         /* structSize */        sizeof(CollisionModifierData),
243         /* type */              eModifierTypeType_OnlyDeform,
244         /* flags */             eModifierTypeFlag_AcceptsMesh
245                                                         | eModifierTypeFlag_Single,
246
247         /* copyData */          0,
248         /* deformVerts */       deformVerts,
249         /* deformMatrices */    0,
250         /* deformVertsEM */     0,
251         /* deformMatricesEM */  0,
252         /* applyModifier */     0,
253         /* applyModifierEM */   0,
254         /* initData */          initData,
255         /* requiredDataMask */  0,
256         /* freeData */          freeData,
257         /* isDisabled */        0,
258         /* updateDepgraph */    0,
259         /* dependsOnTime */     dependsOnTime,
260         /* dependsOnNormals */  0,
261         /* foreachObjectLink */ 0,
262         /* foreachIDLink */     0,
263 };