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