Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/collision.c')
-rw-r--r--source/blender/blenkernel/intern/collision.c301
1 files changed, 121 insertions, 180 deletions
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index f358355912b..05c521e3b94 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -647,6 +647,31 @@ DO_INLINE void collision_interpolateOnTriangle(float to[3],
VECADDMUL(to, v3, w3);
}
+static void cloth_selfcollision_impulse_vert(const float clamp_sq,
+ const float impulse[3],
+ struct ClothVertex *vert)
+{
+ float impulse_len_sq = len_squared_v3(impulse);
+
+ if ((clamp_sq > 0.0f) && (impulse_len_sq > clamp_sq)) {
+ return;
+ }
+
+ if (fabsf(vert->impulse[0]) < fabsf(impulse[0])) {
+ vert->impulse[0] = impulse[0];
+ }
+
+ if (fabsf(vert->impulse[1]) < fabsf(impulse[1])) {
+ vert->impulse[1] = impulse[1];
+ }
+
+ if (fabsf(vert->impulse[2]) < fabsf(impulse[2])) {
+ vert->impulse[2] = impulse[2];
+ }
+
+ vert->impulse_count++;
+}
+
static int cloth_collision_response_static(ClothModifierData *clmd,
CollisionModifierData *collmd,
Object *collob,
@@ -655,18 +680,17 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
const float dt)
{
int result = 0;
- Cloth *cloth1;
- float w1, w2, w3, u1, u2, u3;
- float v1[3], v2[3], relativeVelocity[3];
- float magrelVel;
- float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
- const bool is_hair = (clmd->hairdata != NULL);
-
- cloth1 = clmd->clothObject;
+ Cloth *cloth = clmd->clothObject;
+ const float clamp_sq = square_f(clmd->coll_parms->self_clamp * dt);
+ const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
+ const float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
+ const float min_distance = (clmd->coll_parms->epsilon + epsilon2) * (8.0f / 9.0f);
+ const bool is_hair = (clmd->hairdata != NULL);
for (int i = 0; i < collision_count; i++, collpair++) {
float i1[3], i2[3], i3[3];
-
+ float w1, w2, w3, u1, u2, u3;
+ float v1[3], v2[3], relativeVelocity[3];
zero_v3(i1);
zero_v3(i2);
zero_v3(i3);
@@ -679,25 +703,25 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
/* Compute barycentric coordinates and relative "velocity" for both collision points. */
if (is_hair) {
w2 = line_point_factor_v3(
- collpair->pa, cloth1->verts[collpair->ap1].tx, cloth1->verts[collpair->ap2].tx);
+ collpair->pa, cloth->verts[collpair->ap1].tx, cloth->verts[collpair->ap2].tx);
w1 = 1.0f - w2;
- interp_v3_v3v3(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, w2);
+ interp_v3_v3v3(v1, cloth->verts[collpair->ap1].tv, cloth->verts[collpair->ap2].tv, w2);
}
else {
collision_compute_barycentric(collpair->pa,
- cloth1->verts[collpair->ap1].tx,
- cloth1->verts[collpair->ap2].tx,
- cloth1->verts[collpair->ap3].tx,
+ cloth->verts[collpair->ap1].tx,
+ cloth->verts[collpair->ap2].tx,
+ cloth->verts[collpair->ap3].tx,
&w1,
&w2,
&w3);
collision_interpolateOnTriangle(v1,
- cloth1->verts[collpair->ap1].tv,
- cloth1->verts[collpair->ap2].tv,
- cloth1->verts[collpair->ap3].tv,
+ cloth->verts[collpair->ap1].tv,
+ cloth->verts[collpair->ap2].tv,
+ cloth->verts[collpair->ap3].tv,
w1,
w2,
w3);
@@ -723,16 +747,16 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
/* Calculate the normal component of the relative velocity
* (actually only the magnitude - the direction is stored in 'normal'). */
- magrelVel = dot_v3v3(relativeVelocity, collpair->normal);
+ const float magrelVel = dot_v3v3(relativeVelocity, collpair->normal);
+ const float d = min_distance - collpair->distance;
/* If magrelVel < 0 the edges are approaching each other. */
if (magrelVel > 0.0f) {
/* Calculate Impulse magnitude to stop all motion in normal direction. */
- float magtangent = 0, repulse = 0, d = 0;
+ float magtangent = 0, repulse = 0;
double impulse = 0.0;
float vrel_t_pre[3];
float temp[3];
- float time_multiplier;
/* Calculate tangential velocity. */
copy_v3_v3(temp, collpair->normal);
@@ -750,32 +774,23 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
impulse = magtangent / 1.5;
- VECADDMUL(i1, vrel_t_pre, w1 * impulse);
- VECADDMUL(i2, vrel_t_pre, w2 * impulse);
+ VECADDMUL(i1, vrel_t_pre, (double)w1 * impulse);
+ VECADDMUL(i2, vrel_t_pre, (double)w2 * impulse);
if (!is_hair) {
- VECADDMUL(i3, vrel_t_pre, w3 * impulse);
+ VECADDMUL(i3, vrel_t_pre, (double)w3 * impulse);
}
}
/* Apply velocity stopping impulse. */
impulse = magrelVel / 1.5f;
- VECADDMUL(i1, collpair->normal, w1 * impulse);
- cloth1->verts[collpair->ap1].impulse_count++;
-
- VECADDMUL(i2, collpair->normal, w2 * impulse);
- cloth1->verts[collpair->ap2].impulse_count++;
-
+ VECADDMUL(i1, collpair->normal, (double)w1 * impulse);
+ VECADDMUL(i2, collpair->normal, (double)w2 * impulse);
if (!is_hair) {
- VECADDMUL(i3, collpair->normal, w3 * impulse);
- cloth1->verts[collpair->ap3].impulse_count++;
+ VECADDMUL(i3, collpair->normal, (double)w3 * impulse);
}
- time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
-
- d = clmd->coll_parms->epsilon * 8.0f / 9.0f + epsilon2 * 8.0f / 9.0f - collpair->distance;
-
if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) {
repulse = MIN2(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel);
@@ -790,7 +805,6 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
VECADDMUL(i1, collpair->normal, impulse);
VECADDMUL(i2, collpair->normal, impulse);
-
if (!is_hair) {
VECADDMUL(i3, collpair->normal, impulse);
}
@@ -798,60 +812,26 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
result = 1;
}
- else {
- float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
- float d;
-
- d = clmd->coll_parms->epsilon * 8.0f / 9.0f + epsilon2 * 8.0f / 9.0f - collpair->distance;
-
- if (d > ALMOST_ZERO) {
- /* Stay on the safe side and clamp repulse. */
- float repulse = d / time_multiplier;
- float impulse = repulse / 4.5f;
-
- VECADDMUL(i1, collpair->normal, w1 * impulse);
- VECADDMUL(i2, collpair->normal, w2 * impulse);
+ else if (d > ALMOST_ZERO) {
+ /* Stay on the safe side and clamp repulse. */
+ float repulse = d / time_multiplier;
+ float impulse = repulse / 4.5f;
- if (!is_hair) {
- VECADDMUL(i3, collpair->normal, w3 * impulse);
- }
-
- cloth1->verts[collpair->ap1].impulse_count++;
- cloth1->verts[collpair->ap2].impulse_count++;
-
- if (!is_hair) {
- cloth1->verts[collpair->ap3].impulse_count++;
- }
+ VECADDMUL(i1, collpair->normal, w1 * impulse);
+ VECADDMUL(i2, collpair->normal, w2 * impulse);
- result = 1;
+ if (!is_hair) {
+ VECADDMUL(i3, collpair->normal, w3 * impulse);
}
+
+ result = 1;
}
if (result) {
- float clamp = clmd->coll_parms->clamp * dt;
-
- if ((clamp > 0.0f) &&
- ((len_v3(i1) > clamp) || (len_v3(i2) > clamp) || (len_v3(i3) > clamp))) {
- return 0;
- }
-
- for (int j = 0; j < 3; j++) {
- if (cloth1->verts[collpair->ap1].impulse_count > 0 &&
- fabsf(cloth1->verts[collpair->ap1].impulse[j]) < fabsf(i1[j])) {
- cloth1->verts[collpair->ap1].impulse[j] = i1[j];
- }
-
- if (cloth1->verts[collpair->ap2].impulse_count > 0 &&
- fabsf(cloth1->verts[collpair->ap2].impulse[j]) < fabsf(i2[j])) {
- cloth1->verts[collpair->ap2].impulse[j] = i2[j];
- }
-
- if (!is_hair) {
- if (cloth1->verts[collpair->ap3].impulse_count > 0 &&
- fabsf(cloth1->verts[collpair->ap3].impulse[j]) < fabsf(i3[j])) {
- cloth1->verts[collpair->ap3].impulse[j] = i3[j];
- }
- }
+ cloth_selfcollision_impulse_vert(clamp_sq, i1, &cloth->verts[collpair->ap1]);
+ cloth_selfcollision_impulse_vert(clamp_sq, i2, &cloth->verts[collpair->ap2]);
+ if (!is_hair) {
+ cloth_selfcollision_impulse_vert(clamp_sq, i3, &cloth->verts[collpair->ap3]);
}
}
}
@@ -859,47 +839,22 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
return result;
}
-static void cloth_selfcollision_impulse_vert(const float clamp_sq,
- const float impulse[3],
- struct ClothVertex *vert)
-{
- float impulse_len_sq = len_squared_v3(impulse);
-
- if ((clamp_sq > 0.0f) && (impulse_len_sq > clamp_sq)) {
- return;
- }
-
- if (fabsf(vert->impulse[0]) < fabsf(impulse[0])) {
- vert->impulse[0] = impulse[0];
- }
-
- if (fabsf(vert->impulse[1]) < fabsf(impulse[1])) {
- vert->impulse[1] = impulse[1];
- }
-
- if (fabsf(vert->impulse[2]) < fabsf(impulse[2])) {
- vert->impulse[2] = impulse[2];
- }
-
- vert->impulse_count++;
-}
-
static int cloth_selfcollision_response_static(ClothModifierData *clmd,
CollPair *collpair,
uint collision_count,
const float dt)
{
int result = 0;
- Cloth *cloth1;
- float w1, w2, w3, u1, u2, u3;
- float v1[3], v2[3], relativeVelocity[3];
- float magrelVel;
-
- cloth1 = clmd->clothObject;
+ Cloth *cloth = clmd->clothObject;
+ const float clamp_sq = square_f(clmd->coll_parms->self_clamp * dt);
+ const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
+ const float min_distance = (2.0f * clmd->coll_parms->selfepsilon) * (8.0f / 9.0f);
for (int i = 0; i < collision_count; i++, collpair++) {
float ia[3][3] = {{0.0f}};
float ib[3][3] = {{0.0f}};
+ float w1, w2, w3, u1, u2, u3;
+ float v1[3], v2[3], relativeVelocity[3];
/* Only handle static collisions here. */
if (collpair->flag & (COLLISION_IN_FUTURE | COLLISION_INACTIVE)) {
@@ -908,34 +863,34 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
/* Compute barycentric coordinates for both collision points. */
collision_compute_barycentric(collpair->pa,
- cloth1->verts[collpair->ap1].tx,
- cloth1->verts[collpair->ap2].tx,
- cloth1->verts[collpair->ap3].tx,
+ cloth->verts[collpair->ap1].tx,
+ cloth->verts[collpair->ap2].tx,
+ cloth->verts[collpair->ap3].tx,
&w1,
&w2,
&w3);
collision_compute_barycentric(collpair->pb,
- cloth1->verts[collpair->bp1].tx,
- cloth1->verts[collpair->bp2].tx,
- cloth1->verts[collpair->bp3].tx,
+ cloth->verts[collpair->bp1].tx,
+ cloth->verts[collpair->bp2].tx,
+ cloth->verts[collpair->bp3].tx,
&u1,
&u2,
&u3);
/* Calculate relative "velocity". */
collision_interpolateOnTriangle(v1,
- cloth1->verts[collpair->ap1].tv,
- cloth1->verts[collpair->ap2].tv,
- cloth1->verts[collpair->ap3].tv,
+ cloth->verts[collpair->ap1].tv,
+ cloth->verts[collpair->ap2].tv,
+ cloth->verts[collpair->ap3].tv,
w1,
w2,
w3);
collision_interpolateOnTriangle(v2,
- cloth1->verts[collpair->bp1].tv,
- cloth1->verts[collpair->bp2].tv,
- cloth1->verts[collpair->bp3].tv,
+ cloth->verts[collpair->bp1].tv,
+ cloth->verts[collpair->bp2].tv,
+ cloth->verts[collpair->bp3].tv,
u1,
u2,
u3);
@@ -944,7 +899,8 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
/* Calculate the normal component of the relative velocity
* (actually only the magnitude - the direction is stored in 'normal'). */
- magrelVel = dot_v3v3(relativeVelocity, collpair->normal);
+ const float magrelVel = dot_v3v3(relativeVelocity, collpair->normal);
+ const float d = min_distance - collpair->distance;
/* TODO: Impulses should be weighed by mass as this is self col,
* this has to be done after mass distribution is implemented. */
@@ -952,10 +908,10 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
/* If magrelVel < 0 the edges are approaching each other. */
if (magrelVel > 0.0f) {
/* Calculate Impulse magnitude to stop all motion in normal direction. */
- float magtangent = 0, repulse = 0, d = 0;
+ float magtangent = 0, repulse = 0;
double impulse = 0.0;
float vrel_t_pre[3];
- float temp[3], time_multiplier;
+ float temp[3];
/* Calculate tangential velocity. */
copy_v3_v3(temp, collpair->normal);
@@ -973,29 +929,25 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
impulse = magtangent / 1.5;
- VECADDMUL(ia[0], vrel_t_pre, w1 * impulse);
- VECADDMUL(ia[1], vrel_t_pre, w2 * impulse);
- VECADDMUL(ia[2], vrel_t_pre, w3 * impulse);
+ VECADDMUL(ia[0], vrel_t_pre, (double)w1 * impulse);
+ VECADDMUL(ia[1], vrel_t_pre, (double)w2 * impulse);
+ VECADDMUL(ia[2], vrel_t_pre, (double)w3 * impulse);
- VECADDMUL(ib[0], vrel_t_pre, -u1 * impulse);
- VECADDMUL(ib[1], vrel_t_pre, -u2 * impulse);
- VECADDMUL(ib[2], vrel_t_pre, -u3 * impulse);
+ VECADDMUL(ib[0], vrel_t_pre, (double)u1 * -impulse);
+ VECADDMUL(ib[1], vrel_t_pre, (double)u2 * -impulse);
+ VECADDMUL(ib[2], vrel_t_pre, (double)u3 * -impulse);
}
/* Apply velocity stopping impulse. */
impulse = magrelVel / 3.0f;
- VECADDMUL(ia[0], collpair->normal, w1 * impulse);
- VECADDMUL(ia[1], collpair->normal, w2 * impulse);
- VECADDMUL(ia[2], collpair->normal, w3 * impulse);
-
- VECADDMUL(ib[0], collpair->normal, -u1 * impulse);
- VECADDMUL(ib[1], collpair->normal, -u2 * impulse);
- VECADDMUL(ib[2], collpair->normal, -u3 * impulse);
+ VECADDMUL(ia[0], collpair->normal, (double)w1 * impulse);
+ VECADDMUL(ia[1], collpair->normal, (double)w2 * impulse);
+ VECADDMUL(ia[2], collpair->normal, (double)w3 * impulse);
- time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
-
- d = clmd->coll_parms->selfepsilon * 8.0f / 9.0f * 2.0f - collpair->distance;
+ VECADDMUL(ib[0], collpair->normal, (double)u1 * -impulse);
+ VECADDMUL(ib[1], collpair->normal, (double)u2 * -impulse);
+ VECADDMUL(ib[2], collpair->normal, (double)u3 * -impulse);
if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) {
repulse = MIN2(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel);
@@ -1005,54 +957,43 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
}
repulse = max_ff(impulse, repulse);
-
impulse = repulse / 1.5f;
- VECADDMUL(ia[0], collpair->normal, w1 * impulse);
- VECADDMUL(ia[1], collpair->normal, w2 * impulse);
- VECADDMUL(ia[2], collpair->normal, w3 * impulse);
+ VECADDMUL(ia[0], collpair->normal, (double)w1 * impulse);
+ VECADDMUL(ia[1], collpair->normal, (double)w2 * impulse);
+ VECADDMUL(ia[2], collpair->normal, (double)w3 * impulse);
- VECADDMUL(ib[0], collpair->normal, -u1 * impulse);
- VECADDMUL(ib[1], collpair->normal, -u2 * impulse);
- VECADDMUL(ib[2], collpair->normal, -u3 * impulse);
+ VECADDMUL(ib[0], collpair->normal, (double)u1 * -impulse);
+ VECADDMUL(ib[1], collpair->normal, (double)u2 * -impulse);
+ VECADDMUL(ib[2], collpair->normal, (double)u3 * -impulse);
}
result = 1;
}
- else {
- float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
- float d;
-
- d = clmd->coll_parms->selfepsilon * 8.0f / 9.0f * 2.0f - collpair->distance;
-
- if (d > ALMOST_ZERO) {
- /* Stay on the safe side and clamp repulse. */
- float repulse = d * 1.0f / time_multiplier;
- float impulse = repulse / 9.0f;
+ else if (d > ALMOST_ZERO) {
+ /* Stay on the safe side and clamp repulse. */
+ float repulse = d * 1.0f / time_multiplier;
+ float impulse = repulse / 9.0f;
- VECADDMUL(ia[0], collpair->normal, w1 * impulse);
- VECADDMUL(ia[1], collpair->normal, w2 * impulse);
- VECADDMUL(ia[2], collpair->normal, w3 * impulse);
+ VECADDMUL(ia[0], collpair->normal, w1 * impulse);
+ VECADDMUL(ia[1], collpair->normal, w2 * impulse);
+ VECADDMUL(ia[2], collpair->normal, w3 * impulse);
- VECADDMUL(ib[0], collpair->normal, -u1 * impulse);
- VECADDMUL(ib[1], collpair->normal, -u2 * impulse);
- VECADDMUL(ib[2], collpair->normal, -u3 * impulse);
+ VECADDMUL(ib[0], collpair->normal, u1 * -impulse);
+ VECADDMUL(ib[1], collpair->normal, u2 * -impulse);
+ VECADDMUL(ib[2], collpair->normal, u3 * -impulse);
- result = 1;
- }
+ result = 1;
}
if (result) {
- float clamp_sq = clmd->coll_parms->self_clamp * dt;
- clamp_sq *= clamp_sq;
-
- cloth_selfcollision_impulse_vert(clamp_sq, ia[0], &cloth1->verts[collpair->ap1]);
- cloth_selfcollision_impulse_vert(clamp_sq, ia[1], &cloth1->verts[collpair->ap2]);
- cloth_selfcollision_impulse_vert(clamp_sq, ia[2], &cloth1->verts[collpair->ap3]);
+ cloth_selfcollision_impulse_vert(clamp_sq, ia[0], &cloth->verts[collpair->ap1]);
+ cloth_selfcollision_impulse_vert(clamp_sq, ia[1], &cloth->verts[collpair->ap2]);
+ cloth_selfcollision_impulse_vert(clamp_sq, ia[2], &cloth->verts[collpair->ap3]);
- cloth_selfcollision_impulse_vert(clamp_sq, ib[0], &cloth1->verts[collpair->bp1]);
- cloth_selfcollision_impulse_vert(clamp_sq, ib[1], &cloth1->verts[collpair->bp2]);
- cloth_selfcollision_impulse_vert(clamp_sq, ib[2], &cloth1->verts[collpair->bp3]);
+ cloth_selfcollision_impulse_vert(clamp_sq, ib[0], &cloth->verts[collpair->bp1]);
+ cloth_selfcollision_impulse_vert(clamp_sq, ib[1], &cloth->verts[collpair->bp2]);
+ cloth_selfcollision_impulse_vert(clamp_sq, ib[2], &cloth->verts[collpair->bp3]);
}
}