Fixed some collision response issues. (weekend commit, some half done work in)
This commit is contained in:
@@ -41,11 +41,10 @@ double plNearestPoints(float p[3][3], float q[3][3], float *pa, float *pb, float
|
||||
|
||||
static btGjkEpaPenetrationDepthSolver Solver0;
|
||||
static btMinkowskiPenetrationDepthSolver Solver1;
|
||||
|
||||
|
||||
btConvexPenetrationDepthSolver* Solver = NULL;
|
||||
|
||||
Solver = &Solver1;
|
||||
|
||||
Solver = &Solver0;
|
||||
|
||||
btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver);
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ struct DerivedMesh;
|
||||
|
||||
/* This is approximately the smallest number that can be
|
||||
* represented by a float, given its precision. */
|
||||
#define ALMOST_ZERO 0.0000001
|
||||
#define ALMOST_ZERO 0.00001
|
||||
|
||||
/* Bits to or into the ClothVertex.flags. */
|
||||
#define CVERT_FLAG_PINNED 1
|
||||
@@ -91,6 +91,7 @@ typedef enum
|
||||
CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4), // delete all from cache
|
||||
CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache
|
||||
CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled
|
||||
CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 7), // true if tearing is enabled
|
||||
} CSIMSETT_FLAGS;
|
||||
|
||||
/* Spring types as defined in the paper.*/
|
||||
|
||||
@@ -153,7 +153,7 @@ void cloth_init (ClothModifierData *clmd)
|
||||
clmd->sim_parms.mass = 1.0f;
|
||||
clmd->sim_parms.stepsPerFrame = 5;
|
||||
clmd->sim_parms.sim_time = 1.0;
|
||||
clmd->sim_parms.flags = CSIMSETT_FLAG_RESET;
|
||||
clmd->sim_parms.flags = CSIMSETT_FLAG_RESET | CSIMSETT_FLAG_CCACHE_PROTECT;
|
||||
clmd->sim_parms.solver_type = 0;
|
||||
clmd->sim_parms.preroll = 0;
|
||||
clmd->sim_parms.maxspringlen = 10;
|
||||
@@ -576,6 +576,7 @@ void cloth_cache_set_frame(ClothModifierData *clmd, float time)
|
||||
}
|
||||
}
|
||||
|
||||
// free cloth cache
|
||||
void cloth_cache_free(ClothModifierData *clmd, float time)
|
||||
{
|
||||
Frame *frame = NULL;
|
||||
@@ -659,7 +660,8 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
|
||||
float deltaTime = current_time - clmd->sim_parms.sim_time;
|
||||
|
||||
|
||||
// only be active during a specific period
|
||||
// only be active during a specific period:
|
||||
// that's "first frame" and "last frame" on GUI
|
||||
if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ))
|
||||
{
|
||||
if(current_time < clmd->sim_parms.firstframe)
|
||||
@@ -681,7 +683,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm,
|
||||
}
|
||||
}
|
||||
|
||||
// unused in the moment
|
||||
// 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;
|
||||
@@ -812,46 +814,49 @@ void cloth_free_modifier (ClothModifierData *clmd)
|
||||
return;
|
||||
|
||||
cloth = clmd->clothObject;
|
||||
|
||||
// free our frame cache
|
||||
clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL;
|
||||
cloth_cache_free(clmd, 0);
|
||||
|
||||
if (cloth)
|
||||
{
|
||||
// If our solver provides a free function, call it
|
||||
if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free)
|
||||
{
|
||||
solvers [cloth->old_solver_type].free (clmd);
|
||||
}
|
||||
|
||||
// Free the verts.
|
||||
if (cloth->verts != NULL)
|
||||
MEM_freeN (cloth->verts);
|
||||
|
||||
cloth->verts = NULL;
|
||||
cloth->numverts = -1;
|
||||
|
||||
// Free the springs.
|
||||
if (cloth->springs != NULL)
|
||||
MEM_freeN (cloth->springs);
|
||||
|
||||
cloth->springs = NULL;
|
||||
cloth->numsprings = -1;
|
||||
|
||||
// free BVH collision tree
|
||||
if(cloth->tree)
|
||||
bvh_free((BVH *)cloth->tree);
|
||||
|
||||
// we save our faces for collision objects
|
||||
if(cloth->mfaces)
|
||||
MEM_freeN(cloth->mfaces);
|
||||
|
||||
if(clmd->clothObject->facemarks)
|
||||
MEM_freeN(clmd->clothObject->facemarks);
|
||||
if(!(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_PROTECT))
|
||||
{
|
||||
// free our frame cache
|
||||
clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL;
|
||||
cloth_cache_free(clmd, 0);
|
||||
|
||||
if (cloth)
|
||||
{
|
||||
// If our solver provides a free function, call it
|
||||
if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free)
|
||||
{
|
||||
solvers [cloth->old_solver_type].free (clmd);
|
||||
}
|
||||
|
||||
// Free the verts.
|
||||
if (cloth->verts != NULL)
|
||||
MEM_freeN (cloth->verts);
|
||||
|
||||
cloth->verts = NULL;
|
||||
cloth->numverts = -1;
|
||||
|
||||
// Free the springs.
|
||||
if (cloth->springs != NULL)
|
||||
MEM_freeN (cloth->springs);
|
||||
|
||||
cloth->springs = NULL;
|
||||
cloth->numsprings = -1;
|
||||
|
||||
// free BVH collision tree
|
||||
if(cloth->tree)
|
||||
bvh_free((BVH *)cloth->tree);
|
||||
|
||||
// we save our faces for collision objects
|
||||
if(cloth->mfaces)
|
||||
MEM_freeN(cloth->mfaces);
|
||||
|
||||
MEM_freeN (cloth);
|
||||
clmd->clothObject = NULL;
|
||||
if(clmd->clothObject->facemarks)
|
||||
MEM_freeN(clmd->clothObject->facemarks);
|
||||
|
||||
MEM_freeN (cloth);
|
||||
clmd->clothObject = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -952,6 +957,7 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh
|
||||
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)
|
||||
@@ -993,7 +999,9 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh
|
||||
VECCOPY(verts->xold, verts->x);
|
||||
VECCOPY(verts->txold, verts->x);
|
||||
VECCOPY(verts->tx, verts->x);
|
||||
VecMulf(verts->v, 0.0f);
|
||||
VecMulf(verts->v, 0.0f);
|
||||
verts->impulse_count = 0;
|
||||
VECCOPY(verts->impulse, tnull);
|
||||
}
|
||||
clmd->clothObject->tree = bvh_build(clmd,clmd->coll_parms.epsilon);
|
||||
|
||||
@@ -1159,6 +1167,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
|
||||
// dm->getNumVerts(dm);
|
||||
MVert *mvert = NULL; // CDDM_get_verts(dm);
|
||||
ClothVertex *verts = NULL;
|
||||
float tnull[3] = {0,0,0};
|
||||
|
||||
/* If we have a clothObject, free it. */
|
||||
if (clmd->clothObject != NULL)
|
||||
@@ -1220,6 +1229,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
|
||||
VECCOPY(verts->xconst, verts->x);
|
||||
VECCOPY(verts->txold, verts->x);
|
||||
VecMulf(verts->v, 0.0f);
|
||||
|
||||
verts->impulse_count = 0;
|
||||
VECCOPY(verts->impulse, tnull);
|
||||
}
|
||||
|
||||
/* apply / set vertex groups */
|
||||
@@ -1363,17 +1375,20 @@ int cloth_build_springs(Cloth *cloth, DerivedMesh *dm)
|
||||
|
||||
shear_springs++;
|
||||
temp_index++;
|
||||
|
||||
springs[temp_index].ij = mface[i].v2;
|
||||
springs[temp_index].kl = mface[i].v4;
|
||||
VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co);
|
||||
springs[temp_index].restlen = sqrt(INPR(temp, temp));
|
||||
springs[temp_index].type = SHEAR;
|
||||
|
||||
BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index]));
|
||||
BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index]));
|
||||
|
||||
shear_springs++;
|
||||
|
||||
if(mface[i].v4)
|
||||
{
|
||||
springs[temp_index].ij = mface[i].v2;
|
||||
springs[temp_index].kl = mface[i].v4;
|
||||
VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co);
|
||||
springs[temp_index].restlen = sqrt(INPR(temp, temp));
|
||||
springs[temp_index].type = SHEAR;
|
||||
|
||||
BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index]));
|
||||
BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index]));
|
||||
|
||||
shear_springs++;
|
||||
}
|
||||
}
|
||||
|
||||
// bending springs
|
||||
|
||||
@@ -186,15 +186,15 @@ void generateTriangleMarks()
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
// w3 is not perfect
|
||||
void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], double *w1, double *w2, double *w3)
|
||||
{
|
||||
float tempV1[3], tempV2[3], tempV4[3];
|
||||
double a,b,c,e,f;
|
||||
double tempV1[3], tempV2[3], tempV4[3];
|
||||
double a,b,c,d,e,f;
|
||||
|
||||
VECSUB (tempV1, p1, p3); /* x1 - x3 */
|
||||
VECSUB (tempV2, p2, p3); /* x2 - x3 */
|
||||
VECSUB (tempV4, pv, p3); /* pv - x3 */
|
||||
VECSUB (tempV1, p1, p3);
|
||||
VECSUB (tempV2, p2, p3);
|
||||
VECSUB (tempV4, pv, p3);
|
||||
|
||||
a = INPR (tempV1, tempV1);
|
||||
b = INPR (tempV1, tempV2);
|
||||
@@ -202,10 +202,24 @@ void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3]
|
||||
e = INPR (tempV1, tempV4);
|
||||
f = INPR (tempV2, tempV4);
|
||||
|
||||
d = (a * c - b * b);
|
||||
|
||||
if (ABS(d) < ALMOST_ZERO) {
|
||||
*w1 = *w2 = *w3 = 1.0f / 3.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
w1[0] = (e * c - b * f) / d;
|
||||
|
||||
if(w1[0] < 0)
|
||||
w1[0] = 0.0;
|
||||
|
||||
w1[0] = (e * c - b * f) / (a * c - b * b);
|
||||
w2[0] = (f - b * w1[0]) / c;
|
||||
w3[0] = 1.0 - w1[0] - w2[0];
|
||||
|
||||
if(w2[0] < 0)
|
||||
w2[0] = 0.0;
|
||||
|
||||
w3[0] = 1.0f - w1[0] - w2[0];
|
||||
}
|
||||
|
||||
DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3)
|
||||
@@ -230,36 +244,22 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal
|
||||
|
||||
int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list)
|
||||
{
|
||||
unsigned int i = 0, numverts=0;
|
||||
unsigned int i = 0, numfaces = 0;
|
||||
int result = 0;
|
||||
LinkNode *search = NULL;
|
||||
CollPair *collpair = NULL;
|
||||
Cloth *cloth1, *cloth2;
|
||||
MFace *face1, *face2;
|
||||
double w1, w2, w3, u1, u2, u3;
|
||||
double w1, w2, w3, u1, u2, u3, a1, a2, a3;
|
||||
float v1[3], v2[3], relativeVelocity[3];
|
||||
float magrelVel;
|
||||
|
||||
cloth1 = clmd->clothObject;
|
||||
cloth2 = coll_clmd->clothObject;
|
||||
|
||||
numverts = clmd->clothObject->numverts;
|
||||
|
||||
/*
|
||||
for(i = 0; i < LIST_LENGTH; i++)
|
||||
{
|
||||
// calc SIP-code
|
||||
// TODO for later: calculateSipCode()
|
||||
|
||||
// calc distance (?)
|
||||
numfaces = clmd->clothObject->numfaces;
|
||||
|
||||
// calc impulse
|
||||
|
||||
// apply impulse
|
||||
}
|
||||
*/
|
||||
|
||||
for(i = 0; i < numverts; i++)
|
||||
for(i = 0; i < numfaces; i++)
|
||||
{
|
||||
search = collision_list[i];
|
||||
|
||||
@@ -273,11 +273,13 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link
|
||||
// compute barycentric coordinates for both collision points
|
||||
|
||||
if(!collpair->quadA)
|
||||
{
|
||||
bvh_compute_barycentric(collpair->p1,
|
||||
cloth1->verts[face1->v1].txold,
|
||||
cloth1->verts[face1->v2].txold,
|
||||
cloth1->verts[face1->v3].txold,
|
||||
&w1, &w2, &w3);
|
||||
}
|
||||
else
|
||||
bvh_compute_barycentric(collpair->p1,
|
||||
cloth1->verts[face1->v4].txold,
|
||||
@@ -317,25 +319,26 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link
|
||||
|
||||
// Calculate masses of points.
|
||||
|
||||
// printf("relativeVelocity -> x: %f, y: %f, z: %f\n", relativeVelocity[0], relativeVelocity[1],relativeVelocity[2]);
|
||||
|
||||
// If v_n_mag > 0 the edges are approaching each other.
|
||||
if(magrelVel > ALMOST_ZERO)
|
||||
|
||||
if(magrelVel < -ALMOST_ZERO)
|
||||
{
|
||||
// Calculate Impulse magnitude to stop all motion in normal direction.
|
||||
// const double I_mag = v_n_mag / (1/m1 + 1/m2);
|
||||
float magnitude_i = magrelVel / 2.0f; // TODO implement masses
|
||||
float tangential[3], magtangent, magnormal, collvel[3];
|
||||
float vrel_t_pre[3];
|
||||
float vrel_t[3], impulse;
|
||||
float vrel_t[3];
|
||||
double impulse;
|
||||
float epsilon = clmd->coll_parms.epsilon;
|
||||
float overlap = (epsilon + ALMOST_ZERO-collpair->distance);
|
||||
|
||||
// calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel);
|
||||
|
||||
// magtangent = INPR(tangential, tangential);
|
||||
|
||||
// Apply friction impulse.
|
||||
if (magtangent > ALMOST_ZERO)
|
||||
if (magtangent < ALMOST_ZERO)
|
||||
{
|
||||
|
||||
// printf("friction applied: %f\n", magtangent);
|
||||
@@ -347,57 +350,64 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link
|
||||
VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential);
|
||||
*/
|
||||
}
|
||||
|
||||
impulse = -magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3);
|
||||
VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse);
|
||||
cloth1->verts[face1->v1].impulse_count++;
|
||||
|
||||
VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse);
|
||||
cloth1->verts[face1->v2].impulse_count++;
|
||||
|
||||
VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse);
|
||||
cloth1->verts[face1->v3].impulse_count++;
|
||||
|
||||
if(face1->v4)
|
||||
{
|
||||
VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse);
|
||||
cloth1->verts[face1->v4].impulse_count++;
|
||||
}
|
||||
|
||||
|
||||
if (overlap > ALMOST_ZERO) {
|
||||
double I_mag = overlap * 0.1;
|
||||
|
||||
impulse = I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3);
|
||||
|
||||
VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse);
|
||||
cloth1->verts[face1->v1].impulse_count++;
|
||||
|
||||
VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse);
|
||||
cloth1->verts[face1->v2].impulse_count++;
|
||||
|
||||
VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse);
|
||||
cloth1->verts[face1->v3].impulse_count++;
|
||||
|
||||
if(face1->v4)
|
||||
{
|
||||
VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse);
|
||||
cloth1->verts[face1->v4].impulse_count++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result = 1;
|
||||
|
||||
|
||||
// printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case
|
||||
|
||||
// Apply the impulse and increase impulse counters.
|
||||
// my try, works better than the papers ones (maybe i did just something wrong)
|
||||
VECSUB(collvel, cloth1->verts[face1->v1].tv, v2);
|
||||
magnormal = INPR(collvel, collpair->normal);
|
||||
if(magnormal<ALMOST_ZERO)
|
||||
magnormal = 0.0f;
|
||||
|
||||
impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f;
|
||||
VECADDMUL(cloth1->verts[face1->v1].tv, collpair->normal, -magnormal + impulse);
|
||||
|
||||
|
||||
/*
|
||||
// calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent);
|
||||
|
||||
/*
|
||||
VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal);
|
||||
// VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre));
|
||||
magtangent = Normalize(vrel_t_pre);
|
||||
VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent));
|
||||
|
||||
VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre);
|
||||
*/
|
||||
|
||||
VECSUB(collvel, cloth1->verts[face1->v2].tv, v2);
|
||||
magnormal = INPR(collvel, collpair->normal);
|
||||
if(magnormal<ALMOST_ZERO)
|
||||
magnormal = 0.0f;
|
||||
|
||||
impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f;
|
||||
VECADDMUL(cloth1->verts[face1->v2].tv, collpair->normal, -magnormal+ impulse);
|
||||
*/
|
||||
|
||||
|
||||
VECSUB(collvel, cloth1->verts[face1->v3].tv, v2);
|
||||
magnormal = INPR(collvel, collpair->normal);
|
||||
if(magnormal<ALMOST_ZERO)
|
||||
magnormal = 0.0f;
|
||||
|
||||
impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f;
|
||||
VECADDMUL(cloth1->verts[face1->v3].tv, collpair->normal, -magnormal+ impulse);
|
||||
|
||||
|
||||
VECSUB(collvel, cloth1->verts[face1->v4].tv, v2);
|
||||
magnormal = INPR(collvel, collpair->normal);
|
||||
if(magnormal<ALMOST_ZERO)
|
||||
magnormal = 0.0f;
|
||||
|
||||
impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f;
|
||||
VECADDMUL(cloth1->verts[face1->v4].tv, collpair->normal, -magnormal+ impulse);
|
||||
|
||||
result = 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -444,65 +454,86 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData
|
||||
{
|
||||
if(i == 0)
|
||||
{
|
||||
indexA = face1->v4;
|
||||
indexB = face1->v1;
|
||||
indexC = face1->v3;
|
||||
|
||||
indexD = face2->v1;
|
||||
indexE = face2->v2;
|
||||
indexF = face2->v3;
|
||||
}
|
||||
else if(i == 1)
|
||||
{
|
||||
indexA = face1->v4;
|
||||
indexB = face1->v1;
|
||||
indexC = face1->v3;
|
||||
|
||||
indexD = face2->v4;
|
||||
indexE = face2->v1;
|
||||
indexF = face2->v3;
|
||||
}
|
||||
else if(i == 2)
|
||||
{
|
||||
indexA = face1->v1;
|
||||
indexB = face1->v2;
|
||||
indexC = face1->v3;
|
||||
|
||||
indexD = face2->v4;
|
||||
indexE = face2->v1;
|
||||
indexF = face2->v3;
|
||||
}
|
||||
|
||||
// face a2 + face b1
|
||||
VECCOPY(a[0], cloth1->verts[indexA].txold);
|
||||
VECCOPY(a[1], cloth1->verts[indexB].txold);
|
||||
VECCOPY(a[2], cloth1->verts[indexC].txold);
|
||||
|
||||
|
||||
VECCOPY(b[0], cloth2->verts[indexD].txold);
|
||||
VECCOPY(b[1], cloth2->verts[indexE].txold);
|
||||
VECCOPY(b[2], cloth2->verts[indexF].txold);
|
||||
|
||||
tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal);
|
||||
|
||||
if(tempdistance < distance)
|
||||
{
|
||||
VECCOPY(pa, tpa);
|
||||
VECCOPY(pb, tpb);
|
||||
VECCOPY(normal, tnormal);
|
||||
distance = tempdistance;
|
||||
|
||||
if(i == 0)
|
||||
if(face1->v4)
|
||||
{
|
||||
quadA = 1; quadB = 0;
|
||||
indexA = face1->v4;
|
||||
indexB = face1->v1;
|
||||
indexC = face1->v3;
|
||||
|
||||
indexD = face2->v1;
|
||||
indexE = face2->v2;
|
||||
indexF = face2->v3;
|
||||
}
|
||||
else if(i == 1)
|
||||
else
|
||||
i+=2;
|
||||
}
|
||||
|
||||
if(i == 1)
|
||||
{
|
||||
if((face1->v4)&&(face2->v4))
|
||||
{
|
||||
quadA = quadB = 1;
|
||||
indexA = face1->v4;
|
||||
indexB = face1->v1;
|
||||
indexC = face1->v3;
|
||||
|
||||
indexD = face2->v4;
|
||||
indexE = face2->v1;
|
||||
indexF = face2->v3;
|
||||
}
|
||||
else if(i == 2)
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
if(i == 2)
|
||||
{
|
||||
if(face2->v4)
|
||||
{
|
||||
quadA = 0; quadB = 1;
|
||||
indexA = face1->v1;
|
||||
indexB = face1->v2;
|
||||
indexC = face1->v3;
|
||||
|
||||
indexD = face2->v4;
|
||||
indexE = face2->v1;
|
||||
indexF = face2->v3;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
if(i<3)
|
||||
{
|
||||
// face a2 + face b1
|
||||
VECCOPY(a[0], cloth1->verts[indexA].txold);
|
||||
VECCOPY(a[1], cloth1->verts[indexB].txold);
|
||||
VECCOPY(a[2], cloth1->verts[indexC].txold);
|
||||
|
||||
|
||||
VECCOPY(b[0], cloth2->verts[indexD].txold);
|
||||
VECCOPY(b[1], cloth2->verts[indexE].txold);
|
||||
VECCOPY(b[2], cloth2->verts[indexF].txold);
|
||||
|
||||
tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal);
|
||||
|
||||
if(tempdistance < distance)
|
||||
{
|
||||
VECCOPY(pa, tpa);
|
||||
VECCOPY(pb, tpb);
|
||||
VECCOPY(normal, tnormal);
|
||||
distance = tempdistance;
|
||||
|
||||
if(i == 0)
|
||||
{
|
||||
quadA = 1; quadB = 0;
|
||||
}
|
||||
else if(i == 1)
|
||||
{
|
||||
quadA = quadB = 1;
|
||||
}
|
||||
else if(i == 2)
|
||||
{
|
||||
quadA = 0; quadB = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -524,20 +555,18 @@ void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clm
|
||||
// calc distance + normal
|
||||
distance = implicit_tri_check_coherence(clmd, coll_clmd, tree1->tri_index, tree2->tri_index, collpair->p1, collpair->p2, collpair->vector, collpair->quadA, collpair->quadB);
|
||||
|
||||
if (ABS(distance) <= (epsilon + ALMOST_ZERO))
|
||||
if ((distance <= (epsilon + ALMOST_ZERO)) && (distance > -1.0f)) // max overlap = 1.0
|
||||
{
|
||||
// printf("distance: %f, epsilon: %f\n", (float)distance, epsilon + ALMOST_ZERO);
|
||||
|
||||
// printf("dist: %f\n", (float)distance);
|
||||
|
||||
collpair->face1 = tree1->tri_index;
|
||||
collpair->face2 = tree2->tri_index;
|
||||
|
||||
VECCOPY(collpair->normal, collpair->vector);
|
||||
Normalize(collpair->normal);
|
||||
|
||||
// printf("normal x: %f, y: %f, z: %f\n", collpair->normal[0], collpair->normal[1], collpair->normal[2]);
|
||||
|
||||
collpair->distance = distance;
|
||||
BLI_linklist_append(&linknode[tree1->tri_index], collpair);
|
||||
BLI_linklist_append(&linknode[tree1->tri_index], collpair);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -545,32 +574,14 @@ void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clm
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt)
|
||||
// move collision objects forward in time and update static bounding boxes
|
||||
void cloth_update_collision_objects(float step)
|
||||
{
|
||||
Base *base=NULL;
|
||||
ClothModifierData *coll_clmd=NULL;
|
||||
Cloth *cloth=NULL;
|
||||
Object *coll_ob=NULL;
|
||||
BVH *cloth_bvh=NULL;
|
||||
unsigned int i=0, numverts=0;
|
||||
int result = 0;
|
||||
|
||||
if ((clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
cloth = clmd->clothObject;
|
||||
cloth_bvh = (BVH *) cloth->tree;
|
||||
numverts = clmd->clothObject->numverts;
|
||||
unsigned int i=0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// static collisions
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// update cloth bvh
|
||||
bvh_update_static(clmd, cloth_bvh);
|
||||
|
||||
// search all objects for collision object
|
||||
for (base = G.scene->base.first; base; base = base->next)
|
||||
{
|
||||
@@ -584,73 +595,150 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE
|
||||
if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)
|
||||
{
|
||||
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
|
||||
{
|
||||
unsigned int coll_numverts = coll_clmd->clothObject->numverts;
|
||||
{
|
||||
Cloth *coll_cloth = coll_clmd->clothObject;
|
||||
|
||||
LinkNode **collision_list = MEM_callocN (sizeof(LinkNode *)*numverts, "collision_list");
|
||||
BVH *coll_bvh = coll_clmd->clothObject->tree;
|
||||
unsigned int coll_numverts = coll_cloth->numverts;
|
||||
|
||||
if(collision_list)
|
||||
{
|
||||
// memset(collision_list, 0, sizeof(LinkNode *)*numverts);
|
||||
// update position of collision object
|
||||
for(i = 0; i < coll_numverts; i++)
|
||||
{
|
||||
VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx);
|
||||
|
||||
VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step);
|
||||
|
||||
for(i = 0; i < numverts; i++)
|
||||
{
|
||||
collision_list[i] = NULL;
|
||||
}
|
||||
|
||||
clmd->coll_parms.temp = collision_list;
|
||||
|
||||
// update position of collision object
|
||||
for(i = 0; i < coll_numverts; i++)
|
||||
{
|
||||
VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx);
|
||||
|
||||
VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step);
|
||||
|
||||
VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold);
|
||||
}
|
||||
|
||||
// update BVH of collision object
|
||||
bvh_update_static(coll_clmd, coll_bvh);
|
||||
|
||||
bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response);
|
||||
|
||||
result += collision_static(clmd, coll_clmd, collision_list);
|
||||
|
||||
// calculate velocities
|
||||
|
||||
// free temporary list
|
||||
for(i = 0; i < numverts; i++)
|
||||
{
|
||||
LinkNode *search = collision_list[i];
|
||||
while(search)
|
||||
{
|
||||
LinkNode *next= search->next;
|
||||
CollPair *collpair = search->link;
|
||||
|
||||
if(collpair)
|
||||
MEM_freeN(collpair);
|
||||
|
||||
search = next;
|
||||
}
|
||||
|
||||
BLI_linklist_free(collision_list[i],NULL);
|
||||
}
|
||||
if(collision_list)
|
||||
MEM_freeN(collision_list);
|
||||
|
||||
clmd->coll_parms.temp = NULL;
|
||||
// no dt here because of float rounding errors
|
||||
VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// update BVH of collision object
|
||||
bvh_update_static(coll_clmd, coll_bvh);
|
||||
}
|
||||
else
|
||||
printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define CLOTH_MAX_THRESHOLD 5
|
||||
|
||||
// cloth - object collisions
|
||||
int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt)
|
||||
{
|
||||
Base *base=NULL;
|
||||
ClothModifierData *coll_clmd=NULL;
|
||||
Cloth *cloth=NULL;
|
||||
Object *coll_ob=NULL;
|
||||
BVH *cloth_bvh=NULL;
|
||||
unsigned int i=0, numfaces = 0, numverts = 0;
|
||||
unsigned int result = 0, ic = 0, rounds = 0;
|
||||
ClothVertex *verts = NULL;
|
||||
float tnull[3] = {0,0,0};
|
||||
|
||||
if ((clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
cloth = clmd->clothObject;
|
||||
verts = cloth->verts;
|
||||
cloth_bvh = (BVH *) cloth->tree;
|
||||
numfaces = clmd->clothObject->numfaces;
|
||||
numverts = clmd->clothObject->numverts;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// static collisions
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// update cloth bvh
|
||||
bvh_update_static(clmd, cloth_bvh);
|
||||
|
||||
// update collision objects
|
||||
cloth_update_collision_objects(step);
|
||||
|
||||
do
|
||||
{
|
||||
result = 0;
|
||||
ic = 0;
|
||||
|
||||
// handle all collision objects
|
||||
for (base = G.scene->base.first; base; base = base->next)
|
||||
{
|
||||
|
||||
coll_ob = base->object;
|
||||
coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth);
|
||||
if (!coll_clmd)
|
||||
continue;
|
||||
|
||||
// if collision object go on
|
||||
if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)
|
||||
{
|
||||
if (coll_clmd->clothObject && coll_clmd->clothObject->tree)
|
||||
{
|
||||
LinkNode **collision_list = MEM_callocN (sizeof(LinkNode *)*(numfaces), "collision_list");
|
||||
BVH *coll_bvh = coll_clmd->clothObject->tree;
|
||||
|
||||
if(collision_list)
|
||||
{
|
||||
memset(collision_list, 0, sizeof(LinkNode *)*numfaces);
|
||||
clmd->coll_parms.temp = collision_list;
|
||||
|
||||
bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response);
|
||||
|
||||
result += collision_static(clmd, coll_clmd, collision_list);
|
||||
|
||||
// calculate velocities
|
||||
|
||||
// free temporary list
|
||||
for(i = 0; i < numfaces; i++)
|
||||
{
|
||||
LinkNode *search = collision_list[i];
|
||||
while(search)
|
||||
{
|
||||
LinkNode *next= search->next;
|
||||
CollPair *collpair = search->link;
|
||||
|
||||
if(collpair)
|
||||
MEM_freeN(collpair);
|
||||
|
||||
search = next;
|
||||
}
|
||||
|
||||
BLI_linklist_free(collision_list[i],NULL);
|
||||
}
|
||||
if(collision_list)
|
||||
MEM_freeN(collision_list);
|
||||
|
||||
clmd->coll_parms.temp = NULL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// now apply impulses parallel
|
||||
|
||||
for(i = 0; i < numverts; i++)
|
||||
{
|
||||
if(verts[i].impulse_count)
|
||||
{
|
||||
VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count);
|
||||
VECCOPY(verts[i].impulse, tnull);
|
||||
verts[i].impulse_count = 0;
|
||||
|
||||
ic++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("ic: %d\n", ic);
|
||||
rounds++;
|
||||
}
|
||||
while(result && (CLOTH_MAX_THRESHOLD>rounds));
|
||||
|
||||
printf("\n");
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// update positions + velocities
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1484,7 +1484,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
|
||||
VECCOPY(verts[i].tx, id->Xnew[i]);
|
||||
|
||||
VECSUB(verts[i].tv, verts[i].tx, verts[i].txold);
|
||||
VECSUB(verts[i].v, verts[i].tx, verts[i].txold);
|
||||
VECCOPY(verts[i].v, verts[i].tv);
|
||||
}
|
||||
|
||||
// call collision function
|
||||
|
||||
@@ -4941,9 +4941,12 @@ static int clothModifier_dependsOnTime(ModifierData *md)
|
||||
static void clothModifier_freeData(ModifierData *md)
|
||||
{
|
||||
ClothModifierData *clmd = (ClothModifierData*) md;
|
||||
|
||||
|
||||
if (clmd)
|
||||
cloth_free_modifier (clmd);
|
||||
{
|
||||
clmd->sim_parms.flags &= ~CSIMSETT_FLAG_CCACHE_PROTECT;
|
||||
cloth_free_modifier (clmd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Boolean */
|
||||
|
||||
@@ -41,16 +41,18 @@
|
||||
* is reached.
|
||||
*/
|
||||
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 vertice. */
|
||||
float xold [3]; /* The previous position of this vertice. */
|
||||
float tx [3];
|
||||
float txold [3];
|
||||
float tv[3];
|
||||
float mass; /* mass / weight of the vertex */
|
||||
float goal; /* goal, from SB */
|
||||
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 */
|
||||
float impulse[3]; /* used in collision.c */
|
||||
unsigned int impulse_count; /* same as above */
|
||||
} ClothVertex;
|
||||
|
||||
|
||||
|
||||
@@ -3118,8 +3118,8 @@ static void object_panel_cloth(Object *ob)
|
||||
/* GENERAL STUFF */
|
||||
uiClearButLock();
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 5000.0, 100, 0, "Overall stiffness of structure");
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 1000.0, 1000, 0, "Wrinkle possibility");
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure");
|
||||
uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility");
|
||||
uiDefButI(block, NUM, B_CLOTH_RENEW, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)");
|
||||
uiBlockEndAlign(block);
|
||||
uiBlockBeginAlign(block);
|
||||
@@ -3249,12 +3249,13 @@ static void object_panel_cloth_II(Object *ob)
|
||||
uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll");
|
||||
uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache");
|
||||
if(length>1) // B_CLOTH_CHANGEPREROLL
|
||||
uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame");
|
||||
uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame");
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDefBut(block, LABEL, 0, "No frames cached.", 10,120,290,20, NULL, 0.0, 0, 0, 0, "");
|
||||
}
|
||||
uiDefButBitI(block, TOG, CSIMSETT_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user