WIP commit, (just in case my HD breaks down). Don't expect anything to work. Code...
[blender.git] / source / blender / blenkernel / intern / cloth.c
index d83c7bcb7f0c49c076e2b7879dd3a13efa26d0ca..4c4bac7bbf9806aa0d6a3958503558813b4b23e9 100644 (file)
@@ -120,10 +120,9 @@ static CM_SOLVER_DEF       solvers [] =
 /* ********** cloth engine ******* */
 /* Prototypes for internal functions.
 */
-static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts );
+static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
 static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
-static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts );
-static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts );
+static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
 int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm );
 static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup );
 
@@ -603,132 +602,73 @@ void cloth_cache_free ( ClothModifierData *clmd, float time )
 * cloth_deform_verts - simulates one step, framenr is in frames.
 *
 **/
-void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
-                        float ( *vertexCos ) [3], int numverts )
+DerivedMesh *clothModifier_do(ClothModifierData *clmd,
+                                        Object *ob, DerivedMesh *dm)
 {
        unsigned int i;
-       unsigned int numedges = -1;
-       unsigned int numfaces = -1;
-       MVert *mvert = NULL;
-       MEdge *medge = NULL;
-       MFace *mface = NULL;
-       DerivedMesh *result = NULL, *result2 = NULL;
+       DerivedMesh *result = NULL;
        Cloth *cloth = clmd->clothObject;
        unsigned int framenr = ( float ) G.scene->r.cfra;
        float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 );
-       ListBase        *effectors = NULL;
-       ClothVertex *newframe= NULL, *verts;
+       ListBase *effectors = NULL;
+       ClothVertex *verts = NULL;
        Frame *frame = NULL;
        LinkNode *search = NULL;
        float deltaTime = current_time - clmd->sim_parms.sim_time;
-
-
+       MVert *mverts = NULL;
+       
+       result = CDDM_copy(dm);
+       
        // only be active during a specific period:
        // that's "first frame" and "last frame" on GUI
-       if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) )
+       if ( clmd->clothObject )
        {
-               if ( clmd->clothObject )
+               if ( clmd->sim_parms.cache )
                {
-                       if ( clmd->sim_parms.cache )
+                       if ( current_time < clmd->sim_parms.firstframe )
                        {
-                               if ( current_time < clmd->sim_parms.firstframe )
+                               int frametime = cloth_cache_first_frame ( clmd );
+                               if ( cloth_cache_search_frame ( clmd, frametime ) )
                                {
-                                       int frametime = cloth_cache_first_frame ( clmd );
-                                       if ( cloth_cache_search_frame ( clmd, frametime ) )
-                                       {
-                                               cloth_cache_get_frame ( clmd, frametime );
-                                               cloth_to_object ( ob, clmd, vertexCos, numverts );
-                                       }
-                                       return;
+                                       cloth_cache_get_frame ( clmd, frametime );
+                                       cloth_to_object ( ob, clmd, result );
                                }
-                               else if ( current_time > clmd->sim_parms.lastframe )
+                               return;
+                       }
+                       else if ( current_time > clmd->sim_parms.lastframe )
+                       {
+                               int frametime = cloth_cache_last_frame ( clmd );
+                               if ( cloth_cache_search_frame ( clmd, frametime ) )
                                {
-                                       int frametime = cloth_cache_last_frame ( clmd );
-                                       if ( cloth_cache_search_frame ( clmd, frametime ) )
-                                       {
-                                               cloth_cache_get_frame ( clmd, frametime );
-                                               cloth_to_object ( ob, clmd, vertexCos, numverts );
-                                       }
-                                       return;
+                                       cloth_cache_get_frame ( clmd, frametime );
+                                       cloth_to_object ( ob, clmd, result );
                                }
-                               else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed
+                               return;
+                       }
+                       else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed
+                       {
+                               if ( cloth_cache_search_frame ( clmd, framenr ) )
                                {
-                                       if ( cloth_cache_search_frame ( clmd, framenr ) )
-                                       {
-                                               cloth_cache_get_frame ( clmd, framenr );
-                                               cloth_to_object ( ob, clmd, vertexCos, numverts );
-                                       }
-                                       clmd->sim_parms.sim_time = current_time;
-                                       return;
+                                       cloth_cache_get_frame ( clmd, framenr );
+                                       cloth_to_object ( ob, clmd, result );
                                }
+                               clmd->sim_parms.sim_time = current_time;
+                               return;
                        }
-
                }
-       }
-
 
+       }
+       
        // unused in the moment, calculated seperately in implicit.c
        clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame;
 
        clmd->sim_parms.sim_time = current_time;
-
-       // check if cloth object was some collision object before and needs freeing now
-       if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) && ( clmd->clothObject != NULL ) && ( clmd->clothObject->old_solver_type == 255 ) )
-       {
-               // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing
-               clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ;
-               cloth_free_modifier ( clmd );
-               clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_COLLOBJ;
-       }
-
-       // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ
-       if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ )
-       {
-               // save next position + time
-               if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) )
-               {
-                       if ( !collobj_from_object ( ob, clmd, dm, vertexCos, framenr ) )
-                       {
-                               clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ;
-                               cloth_free_modifier ( clmd );
-                               return;
-                       }
-
-                       if ( clmd->clothObject == NULL )
-                               return;
-
-                       cloth = clmd->clothObject;
-               }
-
-               // Save old position
-               clmd->sim_parms.sim_time_old = clmd->sim_parms.sim_time;
-               clmd->sim_parms.sim_time = current_time;
-
-               verts = cloth->verts;
-
-               for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ )
-               {
-                       // Save the previous position.
-                       VECCOPY ( verts->xold, verts->x );
-                       VECCOPY ( verts->txold, verts->x );
-
-                       // Get the current position.
-                       VECCOPY ( verts->x, vertexCos[i] );
-                       Mat4MulVecfl ( ob->obmat, verts->x );
-
-                       // Compute the vertices "velocity".
-                       // (no dt correction here because of float error)
-                       VECSUB ( verts->v, verts->x, verts->xold );
-               }
-
-               return;
-       }
-
+       
        if ( deltaTime == 1.0f )
        {
-               if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) )
+               if ( ( clmd->clothObject == NULL ) || ( dm->getNumVerts(dm) != clmd->clothObject->numverts ) )
                {
-                       if ( !cloth_from_object ( ob, clmd, dm, vertexCos, numverts ) )
+                       if ( !cloth_from_object ( ob, clmd, dm ) )
                                return;
 
                        if ( clmd->clothObject == NULL )
@@ -745,6 +685,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
                        if ( !cloth_cache_search_frame ( clmd, framenr ) )
                        {
                                verts = cloth->verts;
+                               mverts = dm->getVertArray(dm);
 
                                // Force any pinned verts to their constrained location.
                                for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ )
@@ -752,9 +693,8 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
                                        // Save the previous position.
                                        VECCOPY ( verts->xold, verts->xconst );
                                        VECCOPY ( verts->txold, verts->x );
-
                                        // Get the current position.
-                                       VECCOPY ( verts->xconst, vertexCos[i] );
+                                       VECCOPY ( verts->xconst, mverts[i].co );
                                        Mat4MulVecfl ( ob->obmat, verts->xconst );
                                }
 
@@ -776,7 +716,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
                        }
 
                        // Copy the result back to the object.
-                       cloth_to_object ( ob, clmd, vertexCos, numverts );
+                       cloth_to_object ( ob, clmd, result );
 
                        // bvh_free(clmd->clothObject->tree);
                        // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon);
@@ -790,11 +730,12 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
                        if ( cloth_cache_search_frame ( clmd, framenr ) )
                        {
                                cloth_cache_get_frame ( clmd, framenr );
-                               cloth_to_object ( ob, clmd, vertexCos, numverts );
+                               cloth_to_object ( ob, clmd, result );
                        }
                }
        }
-
+       
+       return result;
 }
 
 /* frees all */
@@ -824,6 +765,14 @@ void cloth_free_modifier ( ClothModifierData *clmd )
                        // Free the verts.
                        if ( cloth->verts != NULL )
                                MEM_freeN ( cloth->verts );
+                       
+                       // Free the verts.
+                       if ( cloth->x != NULL )
+                               MEM_freeN ( cloth->x );
+                       
+                       // Free the verts.
+                       if ( cloth->xnew != NULL )
+                               MEM_freeN ( cloth->xnew );
 
                        cloth->verts = NULL;
                        cloth->numverts = 0;
@@ -876,22 +825,24 @@ void cloth_free_modifier ( ClothModifierData *clmd )
 *
 * This function is a modified version of the softbody.c:softbody_to_object() function.
 **/
-static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts )
+static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
 {
        ClothVertex     *verts = NULL;
        unsigned int    i = 0;
+       MVert           *mvert = NULL;
 
        if ( clmd->clothObject )
        {
                verts = clmd->clothObject->verts;
+               mvert = dm->getVertArray(dm);
 
                /* inverse matrix is not uptodate... */
                Mat4Invert ( ob->imat, ob->obmat );
 
-               for ( i = 0; i < numverts; i++, verts++ )
+               for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ )
                {
-                       VECCOPY ( vertexCos[i], verts->x );
-                       Mat4MulVecfl ( ob->imat, vertexCos[i] );        /* softbody is in global coords */
+                       VECCOPY ( mvert[i].co, verts->x );
+                       Mat4MulVecfl ( ob->imat, mvert[i].co ); /* softbody is in global coords */
                }
        }
 }
@@ -956,73 +907,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short
 }
 
 // only meshes supported at the moment
-/* collision objects */
-static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts )
-{
-       unsigned int i;
-       MVert *mvert = NULL;
-       ClothVertex *verts = NULL;
-       float tnull[3] = {0,0,0};
-
-       /* If we have a clothObject, free it. */
-       if ( clmd->clothObject != NULL )
-               cloth_free_modifier ( clmd );
-
-       /* Allocate a new cloth object. */
-       clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" );
-       if ( clmd->clothObject )
-       {
-               clmd->clothObject->old_solver_type = 255;
-               // clmd->clothObject->old_collision_type = 255;
-       }
-       else if ( clmd->clothObject == NULL )
-       {
-               modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." );
-               return 0;
-       }
-
-       switch ( ob->type )
-       {
-               case OB_MESH:
-
-                       // mesh input objects need DerivedMesh
-                       if ( !dm )
-                               return 0;
-
-                       cloth_from_mesh ( ob, clmd, dm );
-
-                       if ( clmd->clothObject != NULL )
-                       {
-                               if ( !dm ) return 0;
-                               if ( !dm->getNumVerts ( dm ) || !dm->getNumFaces ( dm ) ) return 0;
-
-                               mvert = dm->getVertArray ( dm );
-                               verts = clmd->clothObject->verts;
-                               numverts = clmd->clothObject->numverts = dm->getNumVerts ( dm );
-
-                               for ( i = 0; i < numverts; i++, verts++ )
-                               {
-                                       VECCOPY ( verts->x, mvert[i].co );
-                                       Mat4MulVecfl ( ob->obmat, verts->x );
-                                       verts->flags = 0;
-                                       VECCOPY ( verts->xold, verts->x );
-                                       VECCOPY ( verts->txold, verts->x );
-                                       VECCOPY ( verts->tx, verts->x );
-                                       VecMulf ( verts->v, 0.0f );
-                                       verts->impulse_count = 0;
-                                       VECCOPY ( verts->impulse, tnull );
-                               }
-                               // clmd->clothObject->tree =  bvh_build ( dm, clmd->coll_parms.epsilon );
-
-                       }
-
-                       return 1;
-               default: return 0; // TODO - we do not support changing meshes
-       }
-}
-
-// only meshes supported at the moment
-static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts )
+static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
 {
        unsigned int i = 0;
        // dm->getNumVerts(dm);
@@ -1073,7 +958,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh
                                verts = clmd->clothObject->verts;
 
                                /* set initial values */
-                               for ( i = 0; i < numverts; i++, verts++ )
+                               for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ )
                                {
                                        VECCOPY ( verts->x, mvert[i].co );
                                        Mat4MulVecfl ( ob->obmat, verts->x );
@@ -1140,6 +1025,22 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *
                modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." );
                return;
        }
+       
+       clmd->clothObject->x = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_x" );
+       if ( clmd->clothObject->x == NULL )
+       {
+               cloth_free_modifier ( clmd );
+               modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->x." );
+               return;
+       }
+       
+       clmd->clothObject->xnew = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_xnew" );
+       if ( clmd->clothObject->xnew == NULL )
+       {
+               cloth_free_modifier ( clmd );
+               modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xnew." );
+               return;
+       }
 
        // save face information
        clmd->clothObject->numfaces = numfaces;
@@ -1186,7 +1087,10 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in
                cloth->numsprings++;
        
                BLI_linklist_append ( &cloth->springs, spring );
+               
+               return 1;
        }
+       return 0;
 }
 
 int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm )