svn merge -r 12607:12653 https://svn.blender.org/svnroot/bf-blender/trunk/blender...
[blender.git] / source / blender / blenkernel / intern / modifier.c
index 3a6611a2be778d2604a91d51eff4ca0f4885f2df..85dc1ca44fbf7f1af456bd2c31e09260cdb60696 100644 (file)
@@ -52,6 +52,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_armature_types.h"
+#include "DNA_cloth_types.h"
 #include "DNA_effect_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
@@ -72,6 +73,7 @@
 #include "BKE_main.h"
 #include "BKE_anim.h"
 #include "BKE_bad_level_calls.h"
+#include "BKE_collisions.h"
 #include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_utildefines.h"
@@ -85,6 +87,7 @@
 #include "BKE_object.h"
 #include "BKE_mesh.h"
 #include "BKE_softbody.h"
+#include "BKE_cloth.h"
 #include "BKE_material.h"
 #include "depsgraph_private.h"
 
@@ -4932,6 +4935,256 @@ static void softbodyModifier_deformVerts(
        sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
 }
 
+
+/* Cloth */
+
+static void clothModifier_initData(ModifierData *md) 
+{
+       ClothModifierData *clmd = (ClothModifierData*) md;
+       
+       clmd->sim_parms = MEM_callocN(sizeof(SimulationSettings),
+                   "cloth sim parms");
+       clmd->coll_parms = MEM_callocN(sizeof(CollisionSettings),
+                                     "cloth coll parms");
+       
+       cloth_init (clmd);
+}
+/*
+static void clothModifier_deformVerts(
+               ModifierData *md, Object *ob, DerivedMesh *derivedData,
+               float (*vertexCos)[3], int numVerts)
+{
+       DerivedMesh *dm = NULL;
+
+       // if possible use/create DerivedMesh
+       
+       if(derivedData) dm = CDDM_copy(derivedData);
+       else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
+       
+       if(dm)
+       {
+               CDDM_apply_vert_coords(dm, vertexCos);
+               CDDM_calc_normals(dm);
+       }
+       
+       clothModifier_do((ClothModifierData *)md, ob, dm, vertexCos, numVerts);
+       
+       if(dm)
+               dm->release(dm);
+}
+*/
+
+static DerivedMesh *clothModifier_applyModifier(
+                 ModifierData *md, Object *ob, DerivedMesh *derivedData,
+                 int useRenderParams, int isFinalCalc)
+{
+       ClothModifierData *clmd = (ClothModifierData*) md;
+       DerivedMesh *result=NULL;
+
+       result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc);
+
+       if(result)
+       {
+               return result;
+       }
+       return derivedData;
+}
+
+static void clothModifier_updateDepgraph(
+                ModifierData *md, DagForest *forest, Object *ob,
+                DagNode *obNode)
+{
+       ClothModifierData *clmd = (ClothModifierData*) md;
+       
+       Base *base;
+       
+       if(clmd)
+       {
+               for(base = G.scene->base.first; base; base= base->next) 
+               {
+                       Object *ob1= base->object;
+                       if(ob1 != ob)
+                       {
+                               CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision);
+                               if(collmd)
+                               {
+                                       DagNode *curNode = dag_get_node(forest, ob1);
+                                       
+                                       dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+                               
+                               }
+                       }
+               }
+       }       
+}
+
+CustomDataMask clothModifier_requiredDataMask(ModifierData *md)
+{
+       ClothModifierData *clmd = (ClothModifierData *)md;
+       CustomDataMask dataMask = 0;
+
+       /* ask for vertexgroups if we need them */
+       if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
+               if (clmd->sim_parms->vgroup_mass > 0)
+                       dataMask |= (1 << CD_MDEFORMVERT);
+
+       return dataMask;
+}
+
+
+static int clothModifier_dependsOnTime(ModifierData *md)
+{
+       return 1;
+}
+
+static void clothModifier_freeData(ModifierData *md)
+{
+       ClothModifierData *clmd = (ClothModifierData*) md;
+       
+       if (clmd) 
+       {
+               
+               clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT;
+               cloth_free_modifier (clmd);
+               
+               MEM_freeN(clmd->sim_parms);
+               MEM_freeN(clmd->coll_parms);
+       }
+}
+
+/* Collision */
+
+static void collisionModifier_initData(ModifierData *md) 
+{
+       CollisionModifierData *collmd = (CollisionModifierData*) md;
+       
+       collmd->x = NULL;
+       collmd->xnew = NULL;
+       collmd->current_x = NULL;
+       collmd->current_xnew = NULL;
+       collmd->time = -1;
+       collmd->numverts = 0;
+       collmd->tree = NULL;
+}
+
+static void collisionModifier_freeData(ModifierData *md)
+{
+       CollisionModifierData *collmd = (CollisionModifierData*) md;
+       
+       if (collmd) 
+       {
+               if(collmd->tree)
+                       bvh_free(collmd->tree);
+               if(collmd->x)
+                       MEM_freeN(collmd->x);
+               if(collmd->xnew)
+                       MEM_freeN(collmd->xnew);
+               if(collmd->current_x)
+                       MEM_freeN(collmd->current_x);
+               if(collmd->current_xnew)
+                       MEM_freeN(collmd->current_xnew);
+               
+               collmd->x = NULL;
+               collmd->xnew = NULL;
+               collmd->current_x = NULL;
+               collmd->current_xnew = NULL;
+               collmd->time = -1;
+               collmd->numverts = 0;
+               collmd->tree = NULL;
+       }
+}
+
+static int collisionModifier_dependsOnTime(ModifierData *md)
+{
+       return 1;
+}
+
+static void collisionModifier_deformVerts(
+                                     ModifierData *md, Object *ob, DerivedMesh *derivedData,
+         float (*vertexCos)[3], int numVerts)
+{
+       CollisionModifierData *collmd = (CollisionModifierData*) md;
+       DerivedMesh *dm = NULL;
+       float current_time = 0;
+       unsigned int numverts = 0, i = 0;
+       MVert *tempVert = NULL;
+
+       // if possible use/create DerivedMesh
+       
+       if(derivedData) dm = CDDM_copy(derivedData);
+       else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
+       
+       if(!ob->pd)
+       {
+               printf("collisionModifier_deformVerts: Should not happen!\n");
+               return;
+       }
+       
+       if(dm)
+       {
+               CDDM_apply_vert_coords(dm, vertexCos);
+               CDDM_calc_normals(dm);
+       
+       
+               current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 );
+               
+               if(current_time > collmd->time)
+               {
+                       numverts = dm->getNumVerts ( dm );
+                       
+                       // check if mesh has changed
+                       if(collmd->x && (numverts != collmd->numverts))
+                               collisionModifier_freeData((ModifierData *)collmd);
+                       
+                       if(collmd->time == -1) // first time
+                       {
+                               collmd->x = dm->dupVertArray(dm); // frame start position
+                               
+                               for ( i = 0; i < numverts; i++ )
+                               {
+                                       // we save global positions
+                                       Mat4MulVecfl ( ob->obmat, collmd->x[i].co );
+                               }
+                               
+                               collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
+                               collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
+                               collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
+                               collmd->numverts = numverts;
+                               
+                               // TODO: epsilon
+                               // create bounding box hierarchy
+                               collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, numverts, ob->pd->pdef_sbift);
+                       }
+                       else if(numverts == collmd->numverts)
+                       {
+                               // put positions to old positions
+                               tempVert = collmd->x;
+                               collmd->x = collmd->xnew;
+                               collmd->xnew = tempVert;
+                               
+                               memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
+                               
+                               for ( i = 0; i < numverts; i++ )
+                               {
+                                       // we save global positions
+                                       Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co );
+                               }
+                               
+                               memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert));
+                               memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert));
+                               
+                               // recalc static bounding boxes
+                               bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0);
+                       }
+                       
+                       collmd->time = current_time;
+               }
+       }
+       
+       if(dm)
+               dm->release(dm);
+}
+
 /* Boolean */
 
 static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
@@ -5291,6 +5544,83 @@ static void meshdeformModifier_deformVertsEM(
                dm->release(dm);
 }
 
+
+/* PointCache - example DONT USE SERIOUSLY */
+static void pointCacheModifier_initData(ModifierData *md)
+{
+       PointCacheModifierData *pcm= (PointCacheModifierData*) md;
+
+       pcm->mode= ePointCache_Read; /* read */
+}
+static void pointCacheModifier_freeData(ModifierData *md)
+{
+       PointCacheModifierData *pcm = (PointCacheModifierData*) md;
+}
+static void pointCacheModifier_copyData(ModifierData *md, ModifierData *target)
+{
+       PointCacheModifierData *pcm= (PointCacheModifierData*) md;
+       PointCacheModifierData *tpcm= (PointCacheModifierData*) target;
+
+       tpcm->mode = pcm->mode;
+}
+static int pointCacheModifier_dependsOnTime(ModifierData *md) 
+{
+       return 1;
+}
+CustomDataMask pointCacheModifier_requiredDataMask(ModifierData *md)
+{
+       PointCacheModifierData *pcm= (PointCacheModifierData*) md;
+       CustomDataMask dataMask = 0;
+       return dataMask;
+}
+
+static void pointCacheModifier_deformVerts(
+                                          ModifierData *md, Object *ob, DerivedMesh *derivedData,
+       float (*vertexCos)[3], int numVerts)
+{
+       PointCacheModifierData *pcm = (PointCacheModifierData*) md;
+
+       FILE *fp = NULL;
+       int i;
+       int stack_index = modifiers_indexInObject(ob, md);
+       int totvert;
+       MVert *mvert, *mv;
+       
+       DerivedMesh *dm;
+
+       if(derivedData) dm = CDDM_copy(derivedData);
+       else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
+       else return;
+
+       CDDM_apply_vert_coords(dm, vertexCos);
+       CDDM_calc_normals(dm);
+       
+       mvert = mv = dm->getVertArray(dm);
+       totvert = dm->getNumVerts(dm);
+                       
+       if (pcm->mode == ePointCache_Read) {
+               fp = PTCache_id_fopen((ID *)ob, 'w', G.scene->r.cfra, stack_index);
+               if (!fp) return;
+               for (mv=mvert, i=0; i<totvert; mv++, i++) {
+                       fwrite(&mv->co, sizeof(float), 3, fp);
+               }
+               fclose(fp);
+       } else if (pcm->mode == ePointCache_Write) {
+               float pt[3];
+               fp = PTCache_id_fopen((ID *)ob, 'r', G.scene->r.cfra, stack_index);
+               if (!fp) return;
+               for (mv=mvert, i=0; i<totvert; mv++, i++) {
+                       float *co = vertexCos[i];
+                       if ((fread(co, sizeof(float), 3, fp)) != 3) {
+                               break;
+                       }
+               }
+               fclose(fp);
+       }
+       
+       if(!derivedData) dm->release(dm);
+}
+
 /***/
 
 static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
@@ -5511,6 +5841,32 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
                mti->flags = eModifierTypeFlag_AcceptsCVs
                             | eModifierTypeFlag_RequiresOriginalData;
                mti->deformVerts = softbodyModifier_deformVerts;
+       
+               mti = INIT_TYPE(Cloth);
+               mti->type = eModifierTypeType_Nonconstructive;
+               mti->initData = clothModifier_initData;
+               mti->flags = eModifierTypeFlag_AcceptsMesh
+                               | eModifierTypeFlag_RequiresOriginalData;
+                                       // | eModifierTypeFlag_SupportsMapping
+                                       // | eModifierTypeFlag_SupportsEditmode 
+                                       // | eModifierTypeFlag_EnableInEditmode;
+               mti->dependsOnTime = clothModifier_dependsOnTime;
+               mti->freeData = clothModifier_freeData; 
+               mti->requiredDataMask = clothModifier_requiredDataMask;
+               // mti->copyData = clothModifier_copyData;
+               // mti->deformVerts = clothModifier_deformVerts;
+               mti->applyModifier = clothModifier_applyModifier;
+               mti->updateDepgraph = clothModifier_updateDepgraph;
+               
+               mti = INIT_TYPE(Collision);
+               mti->type = eModifierTypeType_OnlyDeform;
+               mti->initData = collisionModifier_initData;
+               mti->flags = eModifierTypeFlag_AcceptsMesh 
+                               | eModifierTypeFlag_RequiresOriginalData;
+               mti->dependsOnTime = collisionModifier_dependsOnTime;
+               mti->freeData = collisionModifier_freeData; 
+               mti->deformVerts = collisionModifier_deformVerts;
+               // mti->copyData = collisionModifier_copyData;
 
                mti = INIT_TYPE(Boolean);
                mti->type = eModifierTypeType_Nonconstructive;
@@ -5534,6 +5890,16 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
                mti->updateDepgraph = meshdeformModifier_updateDepgraph;
                mti->deformVerts = meshdeformModifier_deformVerts;
                mti->deformVertsEM = meshdeformModifier_deformVertsEM;
+               
+               mti = INIT_TYPE(PointCache);
+               mti->type = eModifierTypeType_OnlyDeform;
+               mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData;
+               mti->initData = pointCacheModifier_initData;
+               mti->freeData = pointCacheModifier_freeData;
+               mti->copyData = pointCacheModifier_copyData;
+               mti->dependsOnTime = pointCacheModifier_dependsOnTime;
+               mti->requiredDataMask = pointCacheModifier_requiredDataMask;
+               mti->deformVerts = pointCacheModifier_deformVerts;
 
                typeArrInit = 0;
 #undef INIT_TYPE
@@ -5727,6 +6093,13 @@ int modifiers_isSoftbodyEnabled(Object *ob)
        return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
 }
 
+ClothModifierData *modifiers_isClothEnabled(Object *ob)
+{
+       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+
+       return clmd;
+}
+
 LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask)
 {
        LinkNode *dataMasks = NULL;
@@ -5910,3 +6283,27 @@ int modifiers_isDeformed(Object *ob)
        return 0;
 }
 
+/* checks we only have deform modifiers */
+int modifiers_isDeformedOnly(Object *ob)
+{
+       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       ModifierTypeInfo *mti;
+       for (; md; md=md->next) {
+               mti = modifierType_getInfo(md->type);
+               /* TODO - check the modifier is being used! */
+               if (mti->type != eModifierTypeType_OnlyDeform) {
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+int modifiers_indexInObject(Object *ob, ModifierData *md_seek)
+{
+       int i= 0;
+       ModifierData *md;
+       
+       for (md=ob->modifiers.first; (md && md_seek!=md); md=md->next, i++);
+       if (!md) return -1; /* modifier isnt in the object */
+       return i;
+}