Bugfix: Cloth did not work with Dynamic Paint.
authorDaniel Genrich <daniel.genrich@gmx.net>
Fri, 10 Aug 2012 00:04:15 +0000 (00:04 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Fri, 10 Aug 2012 00:04:15 +0000 (00:04 +0000)
Fix 1: Pinned vertices were never released when "unpinned" by Dynamic Paint.

Fix 2: When pinning vertices during simulation, they would get "warped" to their original starting position of frame 1.

Thanks to MiikaH for pointing this out and also for providing the regression blend file: http://wiki.blender.org/uploads/a/ab/Cloth_dynamic_paint.blend

source/blender/blenkernel/BKE_cloth.h
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/implicit.c

index facbcb23dd6ae395130072d53ecce67ebfcf79a4..30b3ab38c6fe660bd85bcbdda73b0d4bb568b973 100644 (file)
@@ -57,7 +57,6 @@ struct CollisionTree;
 /* Bits to or into the ClothVertex.flags. */
 #define CLOTH_VERT_FLAG_PINNED 1
 #define CLOTH_VERT_FLAG_NOSELFCOLL 2 /* vertex NOT used for self collisions */
-#define CLOTH_VERT_FLAG_PINNED_EM 3
 
 /**
  * This structure describes a cloth object against which the
index d1a4b33f8f8ccdde2bb2a98faa20c2c8b5326f5b..af7afe7bf30836c328a77520c520ed89d6af50b4 100644 (file)
@@ -400,8 +400,18 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
                copy_v3_v3(verts->txold, verts->x);
 
                /* Get the current position. */
-               copy_v3_v3(verts->xconst, mvert[i].co);
-               mul_m4_v3(ob->obmat, verts->xconst);
+               if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && 
+                       ((!(cloth->verts[i].flags & CLOTH_VERT_FLAG_PINNED)) 
+                       && (cloth->verts[i].goal > ALMOST_ZERO)))
+               {
+                       copy_v3_v3(verts->xconst, mvert[i].co);
+                       mul_m4_v3(ob->obmat, verts->xconst);
+               }
+               else
+               {
+                       /* This fixed animated goals not to jump back to "first frame position" */
+                       copy_v3_v3(verts->xconst, verts->txold);
+               }
        }
 
        effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights);
@@ -795,13 +805,21 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
        
        if (cloth_uses_vgroup(clmd)) {
                for ( i = 0; i < numverts; i++, verts++ ) {
+
+                       /* Reset Goal values to standard */
+                       if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+                               verts->goal= clmd->sim_parms->defgoal;
+                       else
+                               verts->goal= 0.0f;
+
                        dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT );
                        if ( dvert ) {
-                               for ( j = 0; j < dvert->totweight; j++ ) {
 
+                               for ( j = 0; j < dvert->totweight; j++ ) {
                                        verts->flags &= ~CLOTH_VERT_FLAG_PINNED;
                                        if (( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass-1)) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )) {
                                                verts->goal = dvert->dw [j].weight;
+
                                                /* goalfac= 1.0f; */ /* UNUSED */
                                                
                                                /*
@@ -1082,6 +1100,20 @@ static void cloth_update_springs( ClothModifierData *clmd )
                {
                        spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f;
                }
+               else if(spring->type == CLOTH_SPRING_TYPE_GOAL)
+               {
+                       /* Warning: Appending NEW goal springs does not work because implicit solver would need reset! */
+
+                       /* Activate / Deactivate existing springs */
+                       if ((!(cloth->verts[spring->ij].flags & CLOTH_VERT_FLAG_PINNED)) && (cloth->verts[spring->ij].goal > ALMOST_ZERO))
+                       {
+                               spring->flags &= ~CLOTH_SPRING_FLAG_DEACTIVATE;
+                       }
+                       else
+                       {
+                               spring->flags |= CLOTH_SPRING_FLAG_DEACTIVATE;
+                       }
+               }
                
                search = search->next;
        }
index fdc3a8f4317cac8994ee07df24b3605a229c22a3..616214c21ffc3224e9e2423473a87ba207edd052 100644 (file)
@@ -120,7 +120,7 @@ typedef float lfVector[3];
 typedef struct fmatrix3x3 {
        float m[3][3]; /* 3x3 matrix */
        unsigned int c, r; /* column and row number */
-       int pinned; /* is this vertex allowed to move? */
+       /* int pinned; // is this vertex allowed to move? */
        float n1, n2, n3; /* three normal vectors for collision constrains */
        unsigned int vcount; /* vertex count */
        unsigned int scount; /* spring count */ 
@@ -700,10 +700,32 @@ typedef struct Implicit_Data  {
        fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI, *M; 
 } Implicit_Data;
 
+/* Init constraint matrix */
+static void update_matrixS(ClothVertex *verts, int numverts, fmatrix3x3 *S)
+{
+       unsigned int pinned = 0;
+       int i = 0;
+
+       /* Clear matrix from old vertex constraints */
+       for(i = 0; i < S[0].vcount; i++)
+               S[i].c = S[i].r = 0;
+
+       /* Set new vertex constraints */
+       for (i = 0; i < numverts; i++) {
+               if (verts [i].flags & CLOTH_VERT_FLAG_PINNED) {
+                       S[pinned].c = S[pinned].r = i;
+                       pinned++;
+               }
+       }
+
+       // S is special and needs specific vcount and scount
+       S[0].vcount = pinned; 
+       S[0].scount = 0;
+}
+
 int implicit_init(Object *UNUSED(ob), ClothModifierData *clmd)
 {
        unsigned int i = 0;
-       unsigned int pinned = 0;
        Cloth *cloth = NULL;
        ClothVertex *verts = NULL;
        ClothSpring *spring = NULL;
@@ -743,24 +765,19 @@ int implicit_init(Object *UNUSED(ob), ClothModifierData *clmd)
        id->dV = create_lfvector(cloth->numverts);
        id->z = create_lfvector(cloth->numverts);
        
-       for (i=0;i<cloth->numverts;i++) {
+       id->S[0].vcount = 0;
+
+       for (i = 0; i < cloth->numverts; i++) {
                id->A[i].r = id->A[i].c = id->dFdV[i].r = id->dFdV[i].c = id->dFdX[i].r = id->dFdX[i].c = id->P[i].c = id->P[i].r = id->Pinv[i].c = id->Pinv[i].r = id->bigI[i].c = id->bigI[i].r = id->M[i].r = id->M[i].c = i;
 
-               if (verts [i].flags & CLOTH_VERT_FLAG_PINNED) {
-                       id->S[pinned].pinned = 1;
-                       id->S[pinned].c = id->S[pinned].r = i;
-                       pinned++;
-               }
+               update_matrixS(verts, cloth->numverts, id->S);
                
                initdiag_fmatrixS(id->M[i].m, verts[i].mass);
        }
 
-       // S is special and needs specific vcount and scount
-       id->S[0].vcount = pinned; id->S[0].scount = 0;
-
        // init springs 
        search = cloth->springs;
-       for (i=0;i<cloth->numsprings;i++) {
+       for (i = 0; i < cloth->numsprings; i++) {
                spring = search->link;
                
                // dFdV_start[i].r = big_I[i].r = big_zero[i].r = 
@@ -784,6 +801,7 @@ int implicit_init(Object *UNUSED(ob), ClothModifierData *clmd)
 
        return 1;
 }
+
 int    implicit_free(ClothModifierData *clmd)
 {
        Implicit_Data *id;
@@ -1640,8 +1658,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVec
        search = cloth->springs;
        while (search) {
                // only handle active springs
-               // if (((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)) {}
-               cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX, time);
+               ClothSpring *spring = search->link;
+               if( !(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE))
+                       cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX, time);
 
                search = search->next;
        }
@@ -1650,8 +1669,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVec
        search = cloth->springs;
        while (search) {
                // only handle active springs
-               // if (((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)) 
-               cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX);
+               ClothSpring *spring = search->link;
+               if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE))
+                       cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX);
                search = search->next;
        }
        // printf("\n");
@@ -1781,6 +1801,10 @@ int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase *
        int do_extra_solve;
 
        if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { /* do goal stuff */
+               
+               /* Update vertex constraints for pinned vertices */
+               update_matrixS(verts, cloth->numverts, id->S);
+
                for (i = 0; i < numverts; i++) {
                        // update velocities with constrained velocities from pinned verts
                        if (verts [i].flags & CLOTH_VERT_FLAG_PINNED) {