svn merge -r 31314:31370 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[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
41 #include "BKE_collision.h"
42 #include "BKE_cdderivedmesh.h"
43 #include "BKE_global.h"
44 #include "BKE_modifier.h"
45 #include "BKE_object.h"
46 #include "BKE_pointcache.h"
47 #include "BKE_scene.h"
48
49
50 static void initData(ModifierData *md) 
51 {
52         CollisionModifierData *collmd = (CollisionModifierData*) md;
53         
54         collmd->x = NULL;
55         collmd->xnew = NULL;
56         collmd->current_x = NULL;
57         collmd->current_xnew = NULL;
58         collmd->current_v = NULL;
59         collmd->time = -1000;
60         collmd->numverts = 0;
61         collmd->bvhtree = NULL;
62 }
63
64 static void freeData(ModifierData *md)
65 {
66         CollisionModifierData *collmd = (CollisionModifierData*) md;
67         
68         if (collmd) 
69         {
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 = -1000;
91                 collmd->numverts = 0;
92                 collmd->bvhtree = NULL;
93                 collmd->mfaces = NULL;
94         }
95 }
96
97 static int dependsOnTime(ModifierData *md)
98 {
99         return 1;
100 }
101
102 static void deformVerts(
103                                           ModifierData *md, Object *ob, DerivedMesh *derivedData,
104            float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
105 {
106         CollisionModifierData *collmd = (CollisionModifierData*) md;
107         DerivedMesh *dm = NULL;
108         float current_time = 0;
109         unsigned int numverts = 0, i = 0;
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, ob);
115         
116         if(!ob->pd)
117         {
118                 printf("CollisionModifier deformVerts: Should not happen!\n");
119                 return;
120         }
121         
122         if(dm)
123         {
124                 CDDM_apply_vert_coords(dm, vertexCos);
125                 CDDM_calc_normals(dm);
126                 
127                 current_time = BKE_curframe(md->scene);
128                 
129                 if(G.rt > 0)
130                         printf("current_time %f, collmd->time %f\n", current_time, collmd->time);
131                 
132                 numverts = dm->getNumVerts ( dm );
133                 
134                 if((current_time > collmd->time)|| (BKE_ptcache_get_continue_physics()))
135                 {       
136                         // check if mesh has changed
137                         if(collmd->x && (numverts != collmd->numverts))
138                                 freeData((ModifierData *)collmd);
139                         
140                         if(collmd->time == -1000) // first time
141                         {
142                                 collmd->x = dm->dupVertArray(dm); // frame start position
143                                 
144                                 for ( i = 0; i < numverts; i++ )
145                                 {
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                                 collmd->mfaces = dm->dupFaceArray(dm);
158                                 collmd->numfaces = dm->getNumFaces(dm);
159                                 
160                                 // create bounding box hierarchy
161                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
162                                 
163                                 collmd->time = current_time;
164                         }
165                         else if(numverts == collmd->numverts)
166                         {
167                                 // put positions to old positions
168                                 tempVert = collmd->x;
169                                 collmd->x = collmd->xnew;
170                                 collmd->xnew = tempVert;
171                                 
172                                 memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
173                                 
174                                 for ( i = 0; i < numverts; i++ )
175                                 {
176                                         // we save global positions
177                                         mul_m4_v3( ob->obmat, collmd->xnew[i].co );
178                                 }
179                                 
180                                 memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert));
181                                 memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
182                                 
183                                 /* check if GUI setting has changed for bvh */
184                                 if(collmd->bvhtree) 
185                                 {
186                                         if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree))
187                                         {
188                                                 BLI_bvhtree_free(collmd->bvhtree);
189                                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
190                                         }
191                         
192                                 }
193                                 
194                                 /* happens on file load (ONLY when i decomment changes in readfile.c) */
195                                 if(!collmd->bvhtree)
196                                 {
197                                         collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
198                                 }
199                                 else
200                                 {
201                                         // recalc static bounding boxes
202                                         bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
203                                 }
204                                 
205                                 collmd->time = current_time;
206                         }
207                         else if(numverts != collmd->numverts)
208                         {
209                                 freeData((ModifierData *)collmd);
210                         }
211                         
212                 }
213                 else if(current_time < collmd->time)
214                 {       
215                         freeData((ModifierData *)collmd);
216                 }
217                 else
218                 {
219                         if(numverts != collmd->numverts)
220                         {
221                                 freeData((ModifierData *)collmd);
222                         }
223                 }
224         }
225         
226         if(dm)
227                 dm->release(dm);
228 }
229
230
231 ModifierTypeInfo modifierType_Collision = {
232         /* name */              "Collision",
233         /* structName */        "CollisionModifierData",
234         /* structSize */        sizeof(CollisionModifierData),
235         /* type */              eModifierTypeType_OnlyDeform,
236         /* flags */             eModifierTypeFlag_AcceptsMesh
237                                                         | eModifierTypeFlag_Single,
238
239         /* copyData */          0,
240         /* deformVerts */       deformVerts,
241         /* deformVertsEM */     0,
242         /* deformMatricesEM */  0,
243         /* applyModifier */     0,
244         /* applyModifierEM */   0,
245         /* initData */          initData,
246         /* requiredDataMask */  0,
247         /* freeData */          freeData,
248         /* isDisabled */        0,
249         /* updateDepgraph */    0,
250         /* dependsOnTime */     dependsOnTime,
251         /* foreachObjectLink */ 0,
252         /* foreachIDLink */     0,
253 };