diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 5379f0478d3..6b1110d6625 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -173,6 +173,8 @@ typedef struct Frame ClothSpring *springs; unsigned int numverts, numsprings; float time; /* we need float since we want to support sub-frames */ + float (*x)[3]; + float (*xold)[3]; } Frame; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 5c23926e907..c4c32d48b82 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -123,7 +123,7 @@ static CM_SOLVER_DEF solvers [] = static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd); static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr); -static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr); + int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup); /****************************************************************************** @@ -179,6 +179,7 @@ void cloth_init (ClothModifierData *clmd) // unused in the moment, cloth needs quads from mesh DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) { + /* DerivedMesh *result = NULL; int i; int numverts = dm->getNumVerts(dm); @@ -234,11 +235,11 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) MFace *inMF; inMF = &mface[a]; - /* - DM_copy_face_data(dm, result, a, i, 1); + + // DM_copy_face_data(dm, result, a, i, 1); - *mf = *inMF; - */ + // *mf = *inMF; + if(mface[a].v4 && random==1) { @@ -265,11 +266,11 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) i++; mf2 = &mface2[i]; - /* - DM_copy_face_data(dm, result, a, i, 1); + + // DM_copy_face_data(dm, result, a, i, 1); - *mf2 = *inMF; - */ + // *mf2 = *inMF; + if(random==1) { @@ -296,7 +297,9 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) CDDM_calc_normals(result); return result; - + */ + + return NULL; } @@ -395,6 +398,8 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) return result; */ + + return NULL; } @@ -505,6 +510,11 @@ void cloth_cache_get_frame ( ClothModifierData *clmd, float time ) } memcpy ( clmd->clothObject->verts, frame->verts, sizeof ( ClothVertex ) *frame->numverts ); + + memcpy ( clmd->clothObject->x, frame->x, sizeof ( float ) *frame->numverts * 3); + + memcpy ( clmd->clothObject->xold, frame->xold, sizeof ( float ) *frame->numverts * 3); + implicit_set_positions ( clmd ); return; @@ -519,7 +529,6 @@ void cloth_cache_get_frame ( ClothModifierData *clmd, float time ) void cloth_cache_set_frame ( ClothModifierData *clmd, float time ) { Frame *frame = NULL; - LinkNode *search = NULL; if ( clmd->clothObject ) { @@ -536,7 +545,26 @@ void cloth_cache_set_frame ( ClothModifierData *clmd, float time ) MEM_freeN ( frame ); return; } - + + frame->x = MEM_dupallocN ( clmd->clothObject->x ); + + if ( !frame->x ) + { + MEM_freeN ( frame->verts ); + MEM_freeN ( frame ); + return; + } + + frame->xold = MEM_dupallocN ( clmd->clothObject->xold ); + + if ( !frame->xold ) + { + MEM_freeN ( frame->verts ); + MEM_freeN ( frame->x ); + MEM_freeN ( frame ); + return; + } + BLI_linklist_append ( &clmd->sim_parms.cache, frame ); } @@ -570,6 +598,14 @@ void cloth_cache_free ( ClothModifierData *clmd, float time ) { MEM_freeN ( frame->verts ); } + if ( frame->x ) + { + MEM_freeN ( frame->x ); + } + if ( frame->xold ) + { + MEM_freeN ( frame->xold ); + } MEM_freeN ( frame ); lastsearch->next = search->next; @@ -609,22 +645,35 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d 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; - Frame *frame = NULL; - LinkNode *search = NULL; + ListBase *effectors = NULL; + ClothVertex *verts = NULL; float deltaTime = current_time - clmd->sim_parms.sim_time; clmd->sim_parms.dt = 1.0f / (clmd->sim_parms.stepsPerFrame * G.scene->r.frs_sec); result = CDDM_copy(dm); + + if(!result) + { + return dm; + } + + numverts = result->getNumVerts(result); + numedges = result->getNumEdges(result); + numfaces = result->getNumFaces(result); + mvert = CDDM_get_verts(result); + medge = CDDM_get_edges(result); + mface = CDDM_get_faces(result); + + clmd->sim_parms.sim_time = current_time; // only be active during a specific period: // that's "first frame" and "last frame" on GUI + /* if ( clmd->clothObject ) { if ( clmd->sim_parms.cache ) @@ -637,7 +686,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_cache_get_frame ( clmd, frametime ); cloth_to_object ( ob, result, clmd ); } - return; + return result; } else if ( current_time > clmd->sim_parms.lastframe ) { @@ -647,7 +696,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_cache_get_frame ( clmd, frametime ); cloth_to_object ( ob, result, clmd ); } - return; + return result; } else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed { @@ -657,23 +706,11 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_to_object ( ob, result, clmd ); } clmd->sim_parms.sim_time = current_time; - return; + return result; } } - - if(!result) - { - return dm; } - - numverts = result->getNumVerts(result); - numedges = result->getNumEdges(result); - numfaces = result->getNumFaces(result); - mvert = CDDM_get_verts(result); - medge = CDDM_get_edges(result); - mface = CDDM_get_faces(result); - - clmd->sim_parms.sim_time = current_time; + */ if(deltaTime == 1.0f) { @@ -695,28 +732,29 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d { if(!cloth_cache_search_frame(clmd, framenr)) { + verts = cloth->verts; + // Force any pinned verts to their constrained location. for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) { // Save the previous position. - VECCOPY ( verts->xold, verts->xconst ); - VECCOPY ( verts->txold, verts->x ); + VECCOPY ( cloth->xold[i], verts->xconst ); + VECCOPY ( cloth->current_xold[i], cloth->x[i] ); // Get the current position. - VECCOPY ( verts->xconst, mverts[i].co ); + VECCOPY ( verts->xconst, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->xconst ); } - + tstart(); - + /* Call the solver. */ - if (solvers [clmd->sim_parms.solver_type].solver) solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors); - + tend(); - - // printf("Cloth simulation time: %f\n", (float)tval()); - + + printf("Cloth simulation time: %f\n", tval()); + cloth_cache_set_frame(clmd, framenr); } @@ -785,8 +823,16 @@ void cloth_free_modifier (ClothModifierData *clmd) MEM_freeN ( cloth->x ); // Free the verts. - if ( cloth->xnew != NULL ) - MEM_freeN ( cloth->xnew ); + if ( cloth->xold != NULL ) + MEM_freeN ( cloth->xold ); + + // Free the verts. + if ( cloth->current_x != NULL ) + MEM_freeN ( cloth->current_x ); + + // Free the verts. + if ( cloth->current_xold != NULL ) + MEM_freeN ( cloth->current_xold ); cloth->verts = NULL; cloth->numverts = -1; @@ -834,23 +880,21 @@ void cloth_free_modifier (ClothModifierData *clmd) **/ static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd) { - ClothVertex *verts = NULL; unsigned int i = 0; MVert *mvert = NULL; unsigned int numverts; + Cloth *cloth = clmd->clothObject; if (clmd->clothObject) { - verts = clmd->clothObject->verts; - /* inverse matrix is not uptodate... */ Mat4Invert (ob->imat, ob->obmat); mvert = CDDM_get_verts(dm); numverts = dm->getNumVerts(dm); - for (i = 0; i < numverts; i++, verts++) + for (i = 0; i < numverts; i++) { - VECCOPY (mvert[i].co, verts->x); + VECCOPY (mvert[i].co, cloth->x[i]); Mat4MulVecfl (ob->imat, mvert[i].co); /* softbody is in global coords */ } } @@ -921,6 +965,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d unsigned int i; unsigned int numverts = dm->getNumVerts(dm); MVert *mvert = CDDM_get_verts(dm); + float tnull[3] = {0,0,0}; /* If we have a clothObject, free it. */ if (clmd->clothObject != NULL) @@ -963,8 +1008,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d /* set initial values */ for (i = 0; i < numverts; ++i) { - VECCOPY (clmd->clothObject->verts [i].x, mvert[i].co); - Mat4MulVecfl(ob->obmat, clmd->clothObject->verts [i].x); + VECCOPY (clmd->clothObject->x[i], mvert[i].co); + Mat4MulVecfl(ob->obmat, clmd->clothObject->x[i]); clmd->clothObject->verts [i].mass = clmd->sim_parms.mass; if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) @@ -972,9 +1017,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d else clmd->clothObject->verts [i].goal= 0.0f; clmd->clothObject->verts [i].flags = 0; - VECCOPY(clmd->clothObject->verts [i].xold, clmd->clothObject->verts [i].x); - VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->verts [i].x); - VECCOPY(clmd->clothObject->verts [i].txold, clmd->clothObject->verts [i].x); + VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); + VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->x[i]); + VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); VecMulf(clmd->clothObject->verts [i].v, 0.0f); clmd->clothObject->verts [i].impulse_count = 0; @@ -991,7 +1036,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->tree = NULL; // bvh_build(clmd, clmd->coll_parms.epsilon); - cloth_cache_set_frame(clmd, 1); + // cloth_cache_set_frame(clmd, 1); } return 1; @@ -1006,7 +1051,6 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d unsigned int numverts = dm->getNumVerts(dm); unsigned int numfaces = dm->getNumFaces(dm); MFace *mface = CDDM_get_faces(dm); - unsigned int i = 0; /* Allocate our vertices. */ @@ -1019,7 +1063,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->x = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_x" ); + clmd->clothObject->x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_x" ); if ( clmd->clothObject->x == NULL ) { cloth_free_modifier ( clmd ); @@ -1027,11 +1071,27 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->xnew = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_xnew" ); - if ( clmd->clothObject->xnew == NULL ) + clmd->clothObject->xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_xold" ); + if ( clmd->clothObject->xold == NULL ) { cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xnew." ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xold." ); + return; + } + + clmd->clothObject->current_x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_x" ); + if ( clmd->clothObject->current_x == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_x." ); + return; + } + + clmd->clothObject->current_xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_xold" ); + if ( clmd->clothObject->current_xold == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_xold." ); return; } @@ -1101,7 +1161,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) EdgeHash *edgehash = NULL; LinkNode *search = NULL, *search2 = NULL; float temp[3]; - + LinkNode *node = NULL, *node2 = NULL; + // error handling if ( numedges==0 ) return 0; @@ -1134,8 +1195,12 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; struct_springs++; - - BLI_linklist_append ( &cloth->springs, spring ); + + if(!i) + node2 = BLI_linklist_append_fast ( &cloth->springs, spring ); + else + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } } @@ -1154,7 +1219,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; if ( mface[i].v4 ) { @@ -1170,7 +1236,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } } @@ -1204,7 +1271,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL ); bend_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } search = search->next; } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index f61e2d22f1c..e28930fa052 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -770,7 +770,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) for(i = 0; i < cloth->numverts; i++) { - VECCOPY(id->X[i], verts[i].x); + VECCOPY(id->X[i], cloth->x[i]); } return 1; @@ -1165,7 +1165,6 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float damping_force[3] = {0,0,0}; float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; Cloth *cloth = clmd->clothObject; - ClothVertex *verts = cloth->verts; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1336,16 +1335,16 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec if(verts [i].goal < SOFTGOALSNAP) { // current_position = xold + t * (newposition - xold) - VECSUB(tvect, verts[i].xconst, verts[i].xold); + VECSUB(tvect, verts[i].xconst, cloth->xold[i]); mul_fvector_S(tvect, tvect, time); - VECADD(tvect, tvect, verts[i].xold); + VECADD(tvect, tvect, cloth->xold[i]); VECSUB(auxvect, tvect, lX[i]); ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms.goalspring)-1.0f ; VECADDS(lF[i], lF[i], auxvect, -ks); // calulate damping forces generated by goals - VECSUB(velgoal,verts[i].xold, verts[i].xconst); + VECSUB(velgoal, cloth->xold[i], verts[i].xconst); kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); @@ -1433,7 +1432,7 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { - unsigned int i=0, j; + unsigned int i=0; float step=0.0f, tf=1.0f; Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts; @@ -1449,7 +1448,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update velocities with constrained velocities from pinned verts if(verts [i].goal >= SOFTGOALSNAP) { - VECSUB(id->V[i], verts[i].xconst, verts[i].xold); + VECSUB(id->V[i], verts[i].xconst, cloth->xold[i]); // VecMulf(id->V[i], 1.0 / dt); } } @@ -1480,15 +1479,15 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase float tvect[3] = {.0,.0,.0}; // VECSUB(tvect, id->Xnew[i], verts[i].xold); mul_fvector_S(tvect, id->V[i], step+dt); - VECADD(tvect, tvect, verts[i].xold); + VECADD(tvect, tvect, cloth->xold[i]); VECCOPY(id->Xnew[i], tvect); } } - VECCOPY(verts[i].tx, id->Xnew[i]); + VECCOPY(cloth->current_x[i], id->Xnew[i]); - VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + VECSUB(verts[i].tv, cloth->current_x[i], cloth->current_xold[i]); VECCOPY(verts[i].v, verts[i].tv); } @@ -1502,16 +1501,16 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase { // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - VECCOPY(verts[i].txold, verts[i].tx); + VECCOPY(cloth->current_xold[i], cloth->current_x[i]); - VECCOPY(id->Xnew[i], verts[i].tx); + VECCOPY(id->Xnew[i], cloth->current_x[i]); VECCOPY(id->Vnew[i], verts[i].tv); VecMulf(id->Vnew[i], 1.0f / dt); } else { - VECCOPY(verts[i].txold, id->Xnew[i]); + VECCOPY(cloth->current_xold[i], id->Xnew[i]); } } @@ -1552,21 +1551,21 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase { if(verts [i].goal < SOFTGOALSNAP) { - VECCOPY(verts[i].txold, id->X[i]); - VECCOPY(verts[i].x, id->X[i]); + VECCOPY(cloth->current_xold[i], id->X[i]); + VECCOPY(cloth->x[i], id->X[i]); VECCOPY(verts[i].v, id->V[i]); } else { - VECCOPY(verts[i].txold, verts[i].xconst); - VECCOPY(verts[i].x, verts[i].xconst); + VECCOPY(cloth->current_xold[i], verts[i].xconst); + VECCOPY(cloth->x[i], verts[i].xconst); VECCOPY(verts[i].v, id->V[i]); } } else { - VECCOPY(verts[i].txold, id->X[i]); - VECCOPY(verts[i].x, id->X[i]); + VECCOPY(cloth->current_xold[i], id->X[i]); + VECCOPY(cloth->x[i], id->X[i]); VECCOPY(verts[i].v, id->V[i]); } } @@ -1582,7 +1581,7 @@ void implicit_set_positions (ClothModifierData *clmd) for(i = 0; i < numverts; i++) { - VECCOPY(id->X[i], verts[i].x); + VECCOPY(id->X[i], cloth->x[i]); VECCOPY(id->V[i], verts[i].v); } } @@ -1841,7 +1840,7 @@ int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *co Cloth *cloth1, *cloth2; ClothVertex *verts1, *verts2; float temp[3]; - + /* cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; @@ -1863,7 +1862,7 @@ int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *co VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); if(ABS(INPR(temp, temp)) < ALMOST_ZERO) return 1; - + */ return 0; } @@ -2109,7 +2108,7 @@ void collisions_update_collision_objects(float step) ClothModifierData *coll_clmd=NULL; Object *coll_ob=NULL; unsigned int i=0; - + /* // search all objects for collision object for (base = G.scene->base.first; base; base = base->next) { @@ -2146,6 +2145,7 @@ void collisions_update_collision_objects(float step) printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } } + */ } diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index b4592e4d724..e1b1e3ce84a 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -45,10 +45,6 @@ typedef struct ClothVertex int flags; /* General flags per vertex. */ float v [3]; /* The velocity of the point. */ float xconst [3]; /* constrained position */ - float x [3]; /* The current position of this vertex. */ - float xold [3]; /* The previous position of this vertex.*/ - float tx [3]; /* temporary position */ - float txold [3]; /* temporary old position */ float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */ float mass; /* mass / weight of the vertex */ float goal; /* goal, from SB */ @@ -159,10 +155,10 @@ typedef struct Cloth struct CollisionTree *tree; /* collision tree for this cloth object */ struct MFace *mfaces; struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ - struct MVert *x; - struct MVert *xnew; - struct MVert *current_x; - struct MVert *current_xnew; + float (*x)[3]; /* The current position of all vertices.*/ + float (*xold)[3]; /* The previous position of all vertices.*/ + float (*current_x)[3]; /* The TEMPORARY current position of all vertices.*/ + float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/ } Cloth;