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:
authorLukas Tönne <lukas.toenne@gmail.com>2014-09-03 13:17:24 +0400
committerLukas Tönne <lukas.toenne@gmail.com>2015-01-20 11:29:56 +0300
commitf98d388fd3b6225101692de994d64955557b3be5 (patch)
treea3b2b937a68031015fdeffc992a3a90997b03cc0 /source/blender/blenkernel
parentdbf78406435b0ebed9fa69d3d1a96c083098b29c (diff)
Extended line/face collision near-check, to allow for distance margins.
The original BLI method for line/triangle intersection returns false in case the line does not actually intersect, but in order to generate repulsion forces we need to also handle contacts inside the margin.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_collision.h3
-rw-r--r--source/blender/blenkernel/intern/collision.c86
2 files changed, 68 insertions, 21 deletions
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index dab5631d716..c0ee5dcc63e 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -91,9 +91,6 @@ typedef struct CollPair {
int ap1, ap2, ap3, bp1, bp2, bp3;
#endif
int pointsb[4];
-
- /* hair collision */
- float va[3], vb[3]; /* */
}
CollPair;
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index e8cad3d6374..de2d2396007 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -1061,6 +1061,7 @@ static bool cloth_points_collision_response_static(ClothModifierData *clmd, Coll
return result;
}
+#if 0
BLI_INLINE void face_normal(float co1[3], float co2[3], float co3[3], float nor[3])
{
float p[3], q[3];
@@ -1069,20 +1070,70 @@ BLI_INLINE void face_normal(float co1[3], float co2[3], float co3[3], float nor[
cross_v3_v3v3(nor, p, q);
normalize_v3(nor);
}
+#endif
+
+BLI_INLINE bool cloth_point_face_collision_params(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3],
+ float r_nor[3], float *r_lambda, float r_uv[2])
+{
+ float p[3], vec1[3], line[3], edge1[3], edge2[3], q[3];
+ float a, f, u, v;
+
+ sub_v3_v3v3(edge1, v1, v0);
+ sub_v3_v3v3(edge2, v2, v0);
+ sub_v3_v3v3(line, p2, p1);
+
+ cross_v3_v3v3(p, line, edge2);
+ a = dot_v3v3(edge1, p);
+ if (a == 0.0f) return 0;
+ f = 1.0f / a;
+
+ sub_v3_v3v3(vec1, p1, v0);
+
+ u = f * dot_v3v3(vec1, p);
+ if ((u < 0.0f) || (u > 1.0f))
+ return false;
+
+ cross_v3_v3v3(q, vec1, edge1);
+
+ v = f * dot_v3v3(line, q);
+ if ((v < 0.0f) || ((u + v) > 1.0f))
+ return false;
+
+ *r_lambda = f * dot_v3v3(edge2, q);
+ /* don't care about 0..1 lambda range here */
+ /*if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f))
+ * return 0;
+ */
+
+ r_uv[0] = u;
+ r_uv[1] = v;
+
+ cross_v3_v3v3(r_nor, edge1, edge2);
+ normalize_v3(r_nor);
+
+ return true;
+}
static CollPair *cloth_point_collpair(float p1[3], float p2[3], MVert *mverts, int bp1, int bp2, int bp3,
- int index_cloth, int index_coll, CollPair *collpair)
+ int index_cloth, int index_coll, float epsilon, CollPair *collpair)
{
float *co1 = mverts[bp1].co, *co2 = mverts[bp2].co, *co3 = mverts[bp3].co;
- float lambda, uv[2];
- float fnor[3], vec[3];
+ float lambda, uv[2], distance1, distance2;
+ float facenor[3], v1p1[3], v1p2[3];
float w[3];
+
+// if (!isect_line_tri_v3(p1, p2, co1, co2, co3, &lambda, uv))
+// return collpair;
- if (!isect_line_tri_v3(p1, p2, co1, co2, co3, &lambda, uv))
+ if (!cloth_point_face_collision_params(p1, p2, co1, co2, co3, facenor, &lambda, uv))
return collpair;
- face_normal(co1, co2, co3, fnor);
- sub_v3_v3v3(vec, p2, p1);
+ sub_v3_v3v3(v1p1, p1, co1);
+ distance1 = dot_v3v3(v1p1, facenor);
+ sub_v3_v3v3(v1p2, p2, co1);
+ distance2 = dot_v3v3(v1p2, facenor);
+ if (distance2 > epsilon || (distance1 < 0.0f && distance2 < 0.0f))
+ return collpair;
collpair->face1 = index_cloth; /* XXX actually not a face, but equivalent index for point */
collpair->face2 = index_coll;
@@ -1096,18 +1147,15 @@ static CollPair *cloth_point_collpair(float p1[3], float p2[3], MVert *mverts, i
* the current updated position that needs to be corrected
*/
copy_v3_v3(collpair->pa, p2);
- collpair->distance = dot_v3v3(fnor, vec) * lambda;
+ collpair->distance = distance2;
+ mul_v3_v3fl(collpair->vector, facenor, distance2);
w[0] = 1.0f - uv[0] - uv[1];
w[1] = uv[0];
w[2] = uv[1];
interp_v3_v3v3v3(collpair->pb, co1, co2, co3, w);
- /* note: face normal smoothing is ignored here,
- * it would probably not work with collision response
- */
- copy_v3_v3(collpair->normal, fnor);
- copy_v3_v3(collpair->vector, vec);
+ copy_v3_v3(collpair->normal, facenor);
collpair->time = lambda;
collpair->flag = 0;
@@ -1117,7 +1165,7 @@ static CollPair *cloth_point_collpair(float p1[3], float p2[3], MVert *mverts, i
//Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned
static CollPair* cloth_point_collision(ModifierData *md1, ModifierData *md2,
- BVHTreeOverlap *overlap, CollPair *collpair, float UNUSED(dt))
+ BVHTreeOverlap *overlap, float epsilon, CollPair *collpair, float UNUSED(dt))
{
ClothModifierData *clmd = (ClothModifierData *)md1;
CollisionModifierData *collmd = (CollisionModifierData *) md2;
@@ -1129,16 +1177,16 @@ static CollPair* cloth_point_collision(ModifierData *md1, ModifierData *md2,
vert = &clmd->clothObject->verts[overlap->indexA];
face = &collmd->mfaces[overlap->indexB];
- collpair = cloth_point_collpair(vert->x, vert->tx, mverts, face->v1, face->v2, face->v3, overlap->indexA, overlap->indexB, collpair);
+ collpair = cloth_point_collpair(vert->x, vert->tx, mverts, face->v1, face->v2, face->v3, overlap->indexA, overlap->indexB, epsilon, collpair);
if (face->v4)
- collpair = cloth_point_collpair(vert->x, vert->tx, mverts, face->v3, face->v4, face->v1, overlap->indexA, overlap->indexB, collpair);
+ collpair = cloth_point_collpair(vert->x, vert->tx, mverts, face->v3, face->v4, face->v1, overlap->indexA, overlap->indexB, epsilon, collpair);
return collpair;
}
static void cloth_points_objcollisions_nearcheck(ClothModifierData * clmd, CollisionModifierData *collmd,
CollPair **collisions, CollPair **collisions_index,
- int numresult, BVHTreeOverlap *overlap, double dt)
+ int numresult, BVHTreeOverlap *overlap, float epsilon, double dt)
{
int i;
@@ -1148,7 +1196,7 @@ static void cloth_points_objcollisions_nearcheck(ClothModifierData * clmd, Colli
for ( i = 0; i < numresult; i++ ) {
*collisions_index = cloth_point_collision((ModifierData *)clmd, (ModifierData *)collmd,
- overlap+i, *collisions_index, dt);
+ overlap+i, epsilon, *collisions_index, dt);
}
}
@@ -1246,18 +1294,20 @@ int cloth_points_objcollision(Object *ob, ClothModifierData *clmd, float step, f
CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
BVHTreeOverlap *overlap = NULL;
unsigned int result = 0;
+ float epsilon;
if (!collmd->bvhtree)
continue;
/* search for overlapping collision pairs */
overlap = BLI_bvhtree_overlap ( cloth_bvh, collmd->bvhtree, &result );
+ epsilon = BLI_bvhtree_getepsilon(collmd->bvhtree);
// go to next object if no overlap is there
if (result && overlap) {
/* check if collisions really happen (costly near check) */
cloth_points_objcollisions_nearcheck(clmd, collmd, &collisions[i], &collisions_index[i],
- result, overlap, round_dt);
+ result, overlap, epsilon, round_dt);
// resolve nearby collisions
ret += cloth_points_objcollisions_resolve(clmd, collmd, collob->pd, collisions[i], collisions_index[i], round_dt);