Blender  V2.59
MOD_collision.c
Go to the documentation of this file.
00001 /*
00002 * $Id: MOD_collision.c 35614 2011-03-18 15:31:32Z jhk $
00003 *
00004 * ***** BEGIN GPL LICENSE BLOCK *****
00005 *
00006 * This program is free software; you can redistribute it and/or
00007 * modify it under the terms of the GNU General Public License
00008 * as published by the Free Software Foundation; either version 2
00009 * of the License, or (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software  Foundation,
00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 *
00020 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00021 * All rights reserved.
00022 *
00023 * Contributor(s): Daniel Dunbar
00024 *                 Ton Roosendaal,
00025 *                 Ben Batt,
00026 *                 Brecht Van Lommel,
00027 *                 Campbell Barton
00028 *
00029 * ***** END GPL LICENSE BLOCK *****
00030 *
00031 */
00032 
00038 #include "DNA_scene_types.h"
00039 #include "DNA_object_types.h"
00040 #include "DNA_meshdata_types.h"
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "BLI_math.h"
00045 #include "BLI_utildefines.h"
00046 
00047 
00048 #include "BKE_collision.h"
00049 #include "BKE_cdderivedmesh.h"
00050 #include "BKE_global.h"
00051 #include "BKE_modifier.h"
00052 #include "BKE_object.h"
00053 #include "BKE_pointcache.h"
00054 #include "BKE_scene.h"
00055 
00056 #include "MOD_util.h"
00057 
00058 static void initData(ModifierData *md) 
00059 {
00060         CollisionModifierData *collmd = (CollisionModifierData*) md;
00061         
00062         collmd->x = NULL;
00063         collmd->xnew = NULL;
00064         collmd->current_x = NULL;
00065         collmd->current_xnew = NULL;
00066         collmd->current_v = NULL;
00067         collmd->time_x = collmd->time_xnew = -1000;
00068         collmd->numverts = 0;
00069         collmd->bvhtree = NULL;
00070 }
00071 
00072 static void freeData(ModifierData *md)
00073 {
00074         CollisionModifierData *collmd = (CollisionModifierData*) md;
00075         
00076         if (collmd) 
00077         {
00078                 if(collmd->bvhtree)
00079                         BLI_bvhtree_free(collmd->bvhtree);
00080                 if(collmd->x)
00081                         MEM_freeN(collmd->x);
00082                 if(collmd->xnew)
00083                         MEM_freeN(collmd->xnew);
00084                 if(collmd->current_x)
00085                         MEM_freeN(collmd->current_x);
00086                 if(collmd->current_xnew)
00087                         MEM_freeN(collmd->current_xnew);
00088                 if(collmd->current_v)
00089                         MEM_freeN(collmd->current_v);
00090                 if(collmd->mfaces)
00091                         MEM_freeN(collmd->mfaces);
00092                 
00093                 collmd->x = NULL;
00094                 collmd->xnew = NULL;
00095                 collmd->current_x = NULL;
00096                 collmd->current_xnew = NULL;
00097                 collmd->current_v = NULL;
00098                 collmd->time_x = collmd->time_xnew = -1000;
00099                 collmd->numverts = 0;
00100                 collmd->bvhtree = NULL;
00101                 collmd->mfaces = NULL;
00102         }
00103 }
00104 
00105 static int dependsOnTime(ModifierData *UNUSED(md))
00106 {
00107         return 1;
00108 }
00109 
00110 static void deformVerts(ModifierData *md, Object *ob,
00111                                                 DerivedMesh *derivedData,
00112                                                 float (*vertexCos)[3],
00113                                                 int UNUSED(numVerts),
00114                                                 int UNUSED(useRenderParams),
00115                                                 int UNUSED(isFinalCalc))
00116 {
00117         CollisionModifierData *collmd = (CollisionModifierData*) md;
00118         DerivedMesh *dm = NULL;
00119         MVert *tempVert = NULL;
00120         
00121         /* if possible use/create DerivedMesh */
00122         if(derivedData) dm = CDDM_copy(derivedData);
00123         else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
00124         
00125         if(!ob->pd)
00126         {
00127                 printf("CollisionModifier deformVerts: Should not happen!\n");
00128                 return;
00129         }
00130         
00131         if(dm)
00132         {
00133                 float current_time = 0;
00134                 unsigned int numverts = 0;
00135 
00136                 CDDM_apply_vert_coords(dm, vertexCos);
00137                 CDDM_calc_normals(dm);
00138                 
00139                 current_time = BKE_curframe(md->scene);
00140                 
00141                 if(G.rt > 0)
00142                         printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew);
00143                 
00144                 numverts = dm->getNumVerts ( dm );
00145                 
00146                 if((current_time > collmd->time_xnew)|| (BKE_ptcache_get_continue_physics()))
00147                 {
00148                         unsigned int i;
00149 
00150                         // check if mesh has changed
00151                         if(collmd->x && (numverts != collmd->numverts))
00152                                 freeData((ModifierData *)collmd);
00153                         
00154                         if(collmd->time_xnew == -1000) // first time
00155                         {
00156                                 collmd->x = dm->dupVertArray(dm); // frame start position
00157                                 
00158                                 for ( i = 0; i < numverts; i++ )
00159                                 {
00160                                         // we save global positions
00161                                         mul_m4_v3( ob->obmat, collmd->x[i].co );
00162                                 }
00163                                 
00164                                 collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
00165                                 collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
00166                                 collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
00167                                 collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
00168 
00169                                 collmd->numverts = numverts;
00170                                 
00171                                 collmd->mfaces = dm->dupFaceArray(dm);
00172                                 collmd->numfaces = dm->getNumFaces(dm);
00173                                 
00174                                 // create bounding box hierarchy
00175                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
00176                                 
00177                                 collmd->time_x = collmd->time_xnew = current_time;
00178                         }
00179                         else if(numverts == collmd->numverts)
00180                         {
00181                                 // put positions to old positions
00182                                 tempVert = collmd->x;
00183                                 collmd->x = collmd->xnew;
00184                                 collmd->xnew = tempVert;
00185                                 collmd->time_x = collmd->time_xnew;
00186                                 
00187                                 memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
00188                                 
00189                                 for ( i = 0; i < numverts; i++ )
00190                                 {
00191                                         // we save global positions
00192                                         mul_m4_v3( ob->obmat, collmd->xnew[i].co );
00193                                 }
00194                                 
00195                                 memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert));
00196                                 memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
00197                                 
00198                                 /* check if GUI setting has changed for bvh */
00199                                 if(collmd->bvhtree) 
00200                                 {
00201                                         if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree))
00202                                         {
00203                                                 BLI_bvhtree_free(collmd->bvhtree);
00204                                                 collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
00205                                         }
00206                         
00207                                 }
00208                                 
00209                                 /* happens on file load (ONLY when i decomment changes in readfile.c) */
00210                                 if(!collmd->bvhtree)
00211                                 {
00212                                         collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft);
00213                                 }
00214                                 else
00215                                 {
00216                                         // recalc static bounding boxes
00217                                         bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
00218                                 }
00219                                 
00220                                 collmd->time_xnew = current_time;
00221                         }
00222                         else if(numverts != collmd->numverts)
00223                         {
00224                                 freeData((ModifierData *)collmd);
00225                         }
00226                         
00227                 }
00228                 else if(current_time < collmd->time_xnew)
00229                 {       
00230                         freeData((ModifierData *)collmd);
00231                 }
00232                 else
00233                 {
00234                         if(numverts != collmd->numverts)
00235                         {
00236                                 freeData((ModifierData *)collmd);
00237                         }
00238                 }
00239         }
00240         
00241         if(dm)
00242                 dm->release(dm);
00243 }
00244 
00245 
00246 ModifierTypeInfo modifierType_Collision = {
00247         /* name */              "Collision",
00248         /* structName */        "CollisionModifierData",
00249         /* structSize */        sizeof(CollisionModifierData),
00250         /* type */              eModifierTypeType_OnlyDeform,
00251         /* flags */             eModifierTypeFlag_AcceptsMesh
00252                                                         | eModifierTypeFlag_Single,
00253 
00254         /* copyData */          NULL,
00255         /* deformVerts */       deformVerts,
00256         /* deformMatrices */    NULL,
00257         /* deformVertsEM */     NULL,
00258         /* deformMatricesEM */  NULL,
00259         /* applyModifier */     NULL,
00260         /* applyModifierEM */   NULL,
00261         /* initData */          initData,
00262         /* requiredDataMask */  NULL,
00263         /* freeData */          freeData,
00264         /* isDisabled */        NULL,
00265         /* updateDepgraph */    NULL,
00266         /* dependsOnTime */     dependsOnTime,
00267         /* dependsOnNormals */  NULL,
00268         /* foreachObjectLink */ NULL,
00269         /* foreachIDLink */     NULL,
00270 };