Fixed numerical issues, hardened it again.

This commit is contained in:
Daniel Genrich 2007-11-22 17:02:37 +00:00
parent 4cb5470f82
commit 83c1dd78a6
3 changed files with 507 additions and 764 deletions

@ -72,8 +72,8 @@ typedef struct ClothSpring {
int matrix_index; /* needed for implicit solver (fast lookup) */ int matrix_index; /* needed for implicit solver (fast lookup) */
int type; /* types defined in BKE_cloth.h ("springType") */ int type; /* types defined in BKE_cloth.h ("springType") */
int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */
float dfdx[3][4]; float dfdx[3][3];
float dfdv[3][4]; float dfdv[3][3];
float f[3]; float f[3];
} ClothSpring; } ClothSpring;
@ -91,13 +91,13 @@ typedef struct Cloth {
unsigned int numothersprings; unsigned int numothersprings;
unsigned int numspringssave; unsigned int numspringssave;
unsigned int old_solver_type; unsigned int old_solver_type;
float (*x)[4]; /* The current position of all vertices.*/ float (*x)[3]; /* The current position of all vertices.*/
float (*xold)[4]; /* The previous position of all vertices.*/ float (*xold)[3]; /* The previous position of all vertices.*/
float (*current_x)[4]; /* The TEMPORARY current position of all vertices.*/ float (*current_x)[3]; /* The TEMPORARY current position of all vertices.*/
float (*current_xold)[4]; /* The TEMPORARY previous position of all vertices.*/ float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/
float (*v)[4]; /* the current velocity of all vertices */ float (*v)[4]; /* the current velocity of all vertices */
float (*current_v)[4]; float (*current_v)[3];
float (*xconst)[4]; float (*xconst)[3];
} Cloth; } Cloth;
/* goal defines */ /* goal defines */

@ -90,9 +90,9 @@ double tval()
} }
#else #else
#include <sys/time.h> #include <sys/time.h>
static struct timeval _tstart, _tend; static struct timeval _tstart, _tend;
static struct timezone tz; static struct timezone tz;
void tstart ( void ) void tstart ( void )
{ {
gettimeofday ( &_tstart, &tz ); gettimeofday ( &_tstart, &tz );
} }
@ -133,11 +133,11 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v
* *
******************************************************************************/ ******************************************************************************/
/** /**
* cloth_init - creates a new cloth simulation. * cloth_init - creates a new cloth simulation.
* *
* 1. create object * 1. create object
* 2. fill object with standard values or with the GUI settings if given * 2. fill object with standard values or with the GUI settings if given
*/ */
void cloth_init (ClothModifierData *clmd) void cloth_init (ClothModifierData *clmd)
{ {
/* Initialize our new data structure to reasonable values. */ /* Initialize our new data structure to reasonable values. */
@ -202,38 +202,38 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm)
for(i = 0; i < numfaces; i++) for(i = 0; i < numfaces; i++)
{ {
if(mface[i].v4) if(mface[i].v4)
numquads++; numquads++;
else else
numtris++; numtris++;
} }
result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads); result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads);
if(!result) if(!result)
return NULL; return NULL;
// do verts // do verts
mvert2 = CDDM_get_verts(result); mvert2 = CDDM_get_verts(result);
for(a=0; a<numverts; a++) for(a=0; a<numverts; a++)
{ {
MVert *inMV; MVert *inMV;
MVert *mv = &mvert2[a]; MVert *mv = &mvert2[a];
inMV = &mvert[a]; inMV = &mvert[a];
DM_copy_vert_data(dm, result, a, a, 1); DM_copy_vert_data(dm, result, a, a, 1);
*mv = *inMV; *mv = *inMV;
} }
// do faces // do faces
mface2 = CDDM_get_faces(result); mface2 = CDDM_get_faces(result);
for(a=0, i=0; a<numfaces; a++) for(a=0, i=0; a<numfaces; a++)
{ {
MFace *mf = &mface2[i]; MFace *mf = &mface2[i];
MFace *inMF; MFace *inMF;
inMF = &mface[a]; inMF = &mface[a];
// DM_copy_face_data(dm, result, a, i, 1); // DM_copy_face_data(dm, result, a, i, 1);
@ -241,57 +241,57 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm)
// *mf = *inMF; // *mf = *inMF;
if(mface[a].v4 && random==1) if(mface[a].v4 && random==1)
{ {
mf->v1 = mface[a].v2; mf->v1 = mface[a].v2;
mf->v2 = mface[a].v3; mf->v2 = mface[a].v3;
mf->v3 = mface[a].v4; mf->v3 = mface[a].v4;
} }
else else
{ {
mf->v1 = mface[a].v1; mf->v1 = mface[a].v1;
mf->v2 = mface[a].v2; mf->v2 = mface[a].v2;
mf->v3 = mface[a].v3; mf->v3 = mface[a].v3;
} }
mf->v4 = 0; mf->v4 = 0;
mf->flag |= ME_SMOOTH; mf->flag |= ME_SMOOTH;
test_index_face(mf, NULL, 0, 3); test_index_face(mf, NULL, 0, 3);
if(mface[a].v4) if(mface[a].v4)
{ {
MFace *mf2; MFace *mf2;
i++; i++;
mf2 = &mface2[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) if(random==1)
{ {
mf2->v1 = mface[a].v1; mf2->v1 = mface[a].v1;
mf2->v2 = mface[a].v2; mf2->v2 = mface[a].v2;
mf2->v3 = mface[a].v4; mf2->v3 = mface[a].v4;
} }
else else
{ {
mf2->v1 = mface[a].v4; mf2->v1 = mface[a].v4;
mf2->v2 = mface[a].v1; mf2->v2 = mface[a].v1;
mf2->v3 = mface[a].v3; mf2->v3 = mface[a].v3;
} }
mf2->v4 = 0; mf2->v4 = 0;
mf2->flag |= ME_SMOOTH; mf2->flag |= ME_SMOOTH;
test_index_face(mf2, NULL, 0, 3); test_index_face(mf2, NULL, 0, 3);
} }
i++; i++;
} }
CDDM_calc_edges(result); CDDM_calc_edges(result);
CDDM_calc_normals(result); CDDM_calc_normals(result);
@ -330,43 +330,43 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm)
for(i = 0; i < numsprings; i++) for(i = 0; i < numsprings; i++)
{ {
if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) if((springs[i].flags & CSPRING_FLAG_DEACTIVATE)
&&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl)))
{ {
BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL);
BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL);
j++; j++;
} }
} }
// printf("found %d tears\n", j); // printf("found %d tears\n", j);
result = CDDM_from_template(dm, numverts, 0, numfaces); result = CDDM_from_template(dm, numverts, 0, numfaces);
if(!result) if(!result)
return NULL; return NULL;
// do verts // do verts
mvert2 = CDDM_get_verts(result); mvert2 = CDDM_get_verts(result);
for(a=0; a<numverts; a++) for(a=0; a<numverts; a++)
{ {
MVert *inMV; MVert *inMV;
MVert *mv = &mvert2[a]; MVert *mv = &mvert2[a];
inMV = &mvert[a]; inMV = &mvert[a];
DM_copy_vert_data(dm, result, a, a, 1); DM_copy_vert_data(dm, result, a, a, 1);
*mv = *inMV; *mv = *inMV;
} }
// do faces // do faces
mface2 = CDDM_get_faces(result); mface2 = CDDM_get_faces(result);
for(a=0, i=0; a<numfaces; a++) for(a=0, i=0; a<numfaces; a++)
{ {
MFace *mf = &mface2[i]; MFace *mf = &mface2[i];
MFace *inMF; MFace *inMF;
inMF = &mface[a]; inMF = &mface[a];
// DM_copy_face_data(dm, result, a, i, 1); // DM_copy_face_data(dm, result, a, i, 1);
@ -374,21 +374,21 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm)
// *mf = *inMF; // *mf = *inMF;
if((!BLI_edgehash_haskey(edgehash, mface[a].v1, mface[a].v2)) if((!BLI_edgehash_haskey(edgehash, mface[a].v1, mface[a].v2))
&&(!BLI_edgehash_haskey(edgehash, mface[a].v2, mface[a].v3)) &&(!BLI_edgehash_haskey(edgehash, mface[a].v2, mface[a].v3))
&&(!BLI_edgehash_haskey(edgehash, mface[a].v3, mface[a].v4)) &&(!BLI_edgehash_haskey(edgehash, mface[a].v3, mface[a].v4))
&&(!BLI_edgehash_haskey(edgehash, mface[a].v4, mface[a].v1))) &&(!BLI_edgehash_haskey(edgehash, mface[a].v4, mface[a].v1)))
{ {
mf->v1 = mface[a].v1; mf->v1 = mface[a].v1;
mf->v2 = mface[a].v2; mf->v2 = mface[a].v2;
mf->v3 = mface[a].v3; mf->v3 = mface[a].v3;
mf->v4 = mface[a].v4; mf->v4 = mface[a].v4;
test_index_face(mf, NULL, 0, 4); test_index_face(mf, NULL, 0, 4);
i++; i++;
} }
} }
CDDM_lower_num_faces(result, i); CDDM_lower_num_faces(result, i);
CDDM_calc_edges(result); CDDM_calc_edges(result);
@ -527,40 +527,40 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d
/* /*
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 ); int frametime = cloth_cache_first_frame ( clmd );
if ( cloth_cache_search_frame ( clmd, frametime ) ) if ( cloth_cache_search_frame ( clmd, frametime ) )
{ {
cloth_cache_get_frame ( clmd, frametime ); cloth_cache_get_frame ( clmd, frametime );
cloth_to_object ( ob, result, clmd ); cloth_to_object ( ob, result, clmd );
} }
return result; return result;
} }
else if ( current_time > clmd->sim_parms->lastframe ) else if ( current_time > clmd->sim_parms->lastframe )
{ {
int frametime = cloth_cache_last_frame ( clmd ); int frametime = cloth_cache_last_frame ( clmd );
if ( cloth_cache_search_frame ( clmd, frametime ) ) if ( cloth_cache_search_frame ( clmd, frametime ) )
{ {
cloth_cache_get_frame ( clmd, frametime ); cloth_cache_get_frame ( clmd, frametime );
cloth_to_object ( ob, result, clmd ); cloth_to_object ( ob, result, clmd );
} }
return result; return result;
} }
else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed 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_cache_get_frame ( clmd, framenr );
cloth_to_object ( ob, result, clmd ); cloth_to_object ( ob, result, clmd );
} }
clmd->sim_parms->sim_time = current_time; clmd->sim_parms->sim_time = current_time;
return result; return result;
} }
} }
} }
*/ */
if(deltaTime == 1.0f) if(deltaTime == 1.0f)
@ -737,10 +737,10 @@ void cloth_free_modifier (ClothModifierData *clmd)
******************************************************************************/ ******************************************************************************/
/** /**
* cloth_to_object - copies the deformed vertices to the object. * cloth_to_object - copies the deformed vertices to the object.
* *
* This function is a modified version of the softbody.c:softbody_to_object() function. * This function is a modified version of the softbody.c:softbody_to_object() function.
**/ **/
static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd) static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd)
{ {
unsigned int i = 0; unsigned int i = 0;
@ -765,9 +765,9 @@ static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *cl
/** /**
* cloth_apply_vgroup - applies a vertex group as specified by type * cloth_apply_vgroup - applies a vertex group as specified by type
* *
**/ **/
static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup) static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup)
{ {
unsigned int i = 0; unsigned int i = 0;
@ -862,52 +862,51 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
/* create springs */ /* create springs */
clmd->clothObject->springs = NULL; clmd->clothObject->springs = NULL;
clmd->clothObject->numsprings = -1; clmd->clothObject->numsprings = -1;
/* set initial values */
for (i = 0; i < numverts; ++i)
{
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 )
clmd->clothObject->verts [i].goal= clmd->sim_parms->defgoal;
else
clmd->clothObject->verts [i].goal= 0.0;
clmd->clothObject->verts [i].flags = 0;
VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]);
VECCOPY(clmd->clothObject->xconst[i], clmd->clothObject->x[i]);
VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]);
VecMulf(clmd->clothObject->v[i], 0.0);
clmd->clothObject->verts [i].impulse_count = 0;
VECCOPY ( clmd->clothObject->verts [i].impulse, tnull );
}
/* set initial values */ if (!cloth_build_springs (clmd->clothObject, dm) )
for (i = 0; i < numverts; ++i) {
{ modifier_setError (&(clmd->modifier), "Can't build springs.");
VECCOPY (clmd->clothObject->x[i], mvert[i].co); return 0;
Mat4MulVecfl(ob->obmat, clmd->clothObject->x[i]); }
clmd->clothObject->verts [i].mass = clmd->sim_parms->mass; /* apply / set vertex groups */
if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) if (clmd->sim_parms->vgroup_mass > 0)
clmd->clothObject->verts [i].goal= clmd->sim_parms->defgoal; cloth_apply_vgroup (clmd, olddm, clmd->sim_parms->vgroup_mass);
else
clmd->clothObject->verts [i].goal= 0.0; /* init our solver */
clmd->clothObject->verts [i].flags = 0; if (solvers [clmd->sim_parms->solver_type].init)
VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); solvers [clmd->sim_parms->solver_type].init (ob, clmd);
VECCOPY(clmd->clothObject->xconst[i], clmd->clothObject->x[i]);
VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); clmd->clothObject->tree = bvh_build_from_float3(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms->epsilon);
VecMulf(clmd->clothObject->v[i], 0.0);
clmd->clothObject->selftree = bvh_build_from_float3(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms->selfepsilon);
clmd->clothObject->verts [i].impulse_count = 0;
VECCOPY ( clmd->clothObject->verts [i].impulse, tnull ); // save initial state
cloth_write_cache(ob, clmd, framenr-1);
} }
return 1;
if (!cloth_build_springs (clmd->clothObject, dm) ) default: return 0; // TODO - we do not support changing meshes
{
modifier_setError (&(clmd->modifier), "Can't build springs.");
return 0;
}
/* apply / set vertex groups */
if (clmd->sim_parms->vgroup_mass > 0)
cloth_apply_vgroup (clmd, olddm, clmd->sim_parms->vgroup_mass);
/* init our solver */
if (solvers [clmd->sim_parms->solver_type].init)
solvers [clmd->sim_parms->solver_type].init (ob, clmd);
clmd->clothObject->tree = bvh_build_from_float4(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms->epsilon);
clmd->clothObject->selftree = bvh_build_from_float4(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms->selfepsilon);
// save initial state
cloth_write_cache(ob, clmd, framenr-1);
}
return 1;
default: return 0; // TODO - we do not support changing meshes
} }
return 0; return 0;
@ -1119,15 +1118,15 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm )
spring->ij = mface[i].v2; spring->ij = mface[i].v2;
spring->kl = mface[i].v4; spring->kl = mface[i].v4;
VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] );
spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->restlen = sqrt ( INPR ( temp, temp ) );
spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->type = CLOTH_SPRING_TYPE_SHEAR;
BLI_linklist_append ( &edgelist[spring->ij], spring ); BLI_linklist_append ( &edgelist[spring->ij], spring );
BLI_linklist_append ( &edgelist[spring->kl], spring ); BLI_linklist_append ( &edgelist[spring->kl], spring );
shear_springs++; shear_springs++;
node2 = BLI_linklist_append_fast ( &node->next, spring ); node2 = BLI_linklist_append_fast ( &node->next, spring );
node = node2; node = node2;
} }
} }
@ -1148,8 +1147,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm )
// check for existing spring // check for existing spring
// check also if startpoint is equal to endpoint // check also if startpoint is equal to endpoint
if ( !BLI_edgehash_haskey ( edgehash, index2, tspring2->ij ) if ( !BLI_edgehash_haskey ( edgehash, index2, tspring2->ij )
&& !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 ) && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 )
&& ( index2!=tspring2->ij ) ) && ( index2!=tspring2->ij ) )
{ {
spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );

File diff suppressed because it is too large Load Diff