find adjacent triangles while there is no specialized cloth mesh to test bending; draw strech springs instead of countouring triangles; modify contact frame creation

This commit is contained in:
Irlan 2018-05-18 15:51:22 -03:00
parent f52b12dec6
commit e68c50f1c9
2 changed files with 128 additions and 40 deletions

View File

@ -88,10 +88,9 @@ struct b3SharedEdge
u32 nsv1, nsv2; u32 nsv1, nsv2;
}; };
static void b3FindEdges(b3UniqueEdge* uniqueEdges, u32& uniqueCount, b3SharedEdge* sharedEdges, u32& sharedCount, const b3Mesh* m) static u32 b3FindUniqueEdges(b3UniqueEdge* uniqueEdges, const b3Mesh* m)
{ {
uniqueCount = 0; u32 uniqueCount = 0;
sharedCount = 0;
for (u32 i = 0; i < m->triangleCount; ++i) for (u32 i = 0; i < m->triangleCount; ++i)
{ {
@ -131,6 +130,64 @@ static void b3FindEdges(b3UniqueEdge* uniqueEdges, u32& uniqueCount, b3SharedEdg
} }
} }
} }
return uniqueCount;
}
static u32 b3FindSharedEdges(b3SharedEdge* sharedEdges, const b3Mesh* m)
{
u32 sharedCount = 0;
for (u32 i = 0; i < m->triangleCount; ++i)
{
b3Triangle* t1 = m->triangles + i;
u32 i1s[3] = { t1->v1, t1->v2, t1->v3 };
for (u32 j1 = 0; j1 < 3; ++j1)
{
u32 k1 = j1 + 1 < 3 ? j1 + 1 : 0;
u32 t1v1 = i1s[j1];
u32 t1v2 = i1s[k1];
for (u32 j = i + 1; j < m->triangleCount; ++j)
{
b3Triangle* t2 = m->triangles + j;
u32 i2s[3] = { t2->v1, t2->v2, t2->v3 };
for (u32 j2 = 0; j2 < 3; ++j2)
{
u32 k2 = j2 + 1 < 3 ? j2 + 1 : 0;
u32 t2v1 = i2s[j2];
u32 t2v2 = i2s[k2];
if (t1v1 == t2v2 && t1v2 == t2v1)
{
// The triangles are adjacent.
u32 k3 = k1 + 1 < 3 ? k1 + 1 : 0;
u32 t1v3 = i1s[k3];
u32 k4 = k2 + 1 < 3 ? k2 + 1 : 0;
u32 t2v3 = i2s[k4];
// Add shared edge and non-shared vertices.
b3SharedEdge se;
se.v1 = t1v1;
se.v2 = t1v2;
se.nsv1 = t1v3;
se.nsv2 = t2v3;
sharedEdges[sharedCount++] = se;
break;
}
}
}
}
}
return sharedCount;
} }
void b3SpringCloth::Initialize(const b3SpringClothDef& def) void b3SpringCloth::Initialize(const b3SpringClothDef& def)
@ -209,15 +266,20 @@ void b3SpringCloth::Initialize(const b3SpringClothDef& def)
// Initialize springs // Initialize springs
u32 edgeCount = 3 * m->triangleCount; u32 edgeCount = 3 * m->triangleCount;
b3SharedEdge* sharedEdges = (b3SharedEdge*)m_allocator->Allocate(edgeCount * sizeof(b3SharedEdge));
u32 sharedCount = 0;
b3UniqueEdge* uniqueEdges = (b3UniqueEdge*)m_allocator->Allocate(edgeCount * sizeof(b3UniqueEdge)); b3UniqueEdge* uniqueEdges = (b3UniqueEdge*)m_allocator->Allocate(edgeCount * sizeof(b3UniqueEdge));
u32 uniqueCount = 0; u32 uniqueCount = b3FindUniqueEdges(uniqueEdges, m);
b3FindEdges(uniqueEdges, uniqueCount, sharedEdges, sharedCount, m); u32 springCapacity = uniqueCount;
#if B3_CLOTH_BENDING
b3SharedEdge* sharedEdges = (b3SharedEdge*)m_allocator->Allocate(edgeCount * sizeof(b3SharedEdge));
u32 sharedCount = b3FindSharedEdges(sharedEdges, m);
springCapacity += sharedCount;
#endif
u32 springCapacity = uniqueCount + sharedCount;
m_springs = (b3Spring*)b3Alloc(springCapacity * sizeof(b3Spring)); m_springs = (b3Spring*)b3Alloc(springCapacity * sizeof(b3Spring));
// Streching // Streching
@ -241,7 +303,8 @@ void b3SpringCloth::Initialize(const b3SpringClothDef& def)
++m_springCount; ++m_springCount;
} }
#if B3_CLOTH_BENDING == 1 #if B3_CLOTH_BENDING
// Bending // Bending
for (u32 i = 0; i < sharedCount; ++i) for (u32 i = 0; i < sharedCount; ++i)
{ {
@ -260,10 +323,10 @@ void b3SpringCloth::Initialize(const b3SpringClothDef& def)
++m_springCount; ++m_springCount;
} }
#endif // #if B3_CLOTH_BENDING m_allocator->Free(sharedEdges);
#endif
m_allocator->Free(uniqueEdges); m_allocator->Free(uniqueEdges);
m_allocator->Free(sharedEdges);
B3_ASSERT(m_springCount <= springCapacity); B3_ASSERT(m_springCount <= springCapacity);
} }
@ -344,21 +407,6 @@ void b3SpringCloth::GetTension(b3Array<b3Vec3>& T) const
} }
} }
static B3_FORCE_INLINE void b3CreateTangents(b3Vec3& t1, b3Vec3& t2, const b3Vec3& dv, const b3Vec3& n)
{
t1 = dv - b3Dot(dv, n) * n;
if (b3Dot(t1, t1) > B3_EPSILON * B3_EPSILON)
{
t1.Normalize();
t2 = b3Cross(t1, n);
}
else
{
t1 = b3Perp(n);
t2 = b3Cross(t1, n);
}
}
void b3SpringCloth::UpdateContacts() void b3SpringCloth::UpdateContacts()
{ {
for (u32 i = 0; i < m_massCount; ++i) for (u32 i = 0; i < m_massCount; ++i)
@ -369,9 +417,6 @@ void b3SpringCloth::UpdateContacts()
continue; continue;
} }
// Relative velocity
b3Vec3 dv = m_v[i];
b3MassContact* c = m_contacts + i; b3MassContact* c = m_contacts + i;
// Save the old contact // Save the old contact
@ -424,6 +469,8 @@ void b3SpringCloth::UpdateContacts()
// Remember the normal orientation is from shape 2 to shape 1 (mass) // Remember the normal orientation is from shape 2 to shape 1 (mass)
c->j = bestIndex; c->j = bestIndex;
c->n = n; c->n = n;
c->t1 = b3Perp(n);
c->t2 = b3Cross(c->t1, n);
c->lockN = true; c->lockN = true;
// Apply position correction // Apply position correction
@ -472,11 +519,30 @@ void b3SpringCloth::UpdateContacts()
b3Shape* s = m_shapes[c->j]; b3Shape* s = m_shapes[c->j];
b3Vec3 n = c->n; b3Vec3 n = c->n;
float32 friction = s->GetFriction(); float32 u = s->GetFriction();
float32 normalForce = c0.Fn; float32 normalForce = c0.Fn;
// Tangents // Relative velocity
b3CreateTangents(c->t1, c->t2, dv, n); b3Vec3 dv = m_v[i];
b3Vec3 t1 = dv - b3Dot(dv, n) * n;
if (b3Dot(t1, t1) > B3_EPSILON * B3_EPSILON)
{
// Create a dynamic basis
t1.Normalize();
b3Vec3 t2 = b3Cross(t1, n);
t2.Normalize();
c->t1 = t1;
c->t2 = t2;
}
else
{
c->lockT1 = true;
c->lockT2 = true;
continue;
}
b3Vec3 ts[2]; b3Vec3 ts[2];
ts[0] = c->t1; ts[0] = c->t1;
@ -510,7 +576,7 @@ void b3SpringCloth::UpdateContacts()
if (lockT0[k] == true && lockT[k] == true) if (lockT0[k] == true && lockT[k] == true)
{ {
// The contact persists // The contact persists
float32 maxForce = friction * normalForce; float32 maxForce = u * normalForce;
if (Ft0[k] * Ft0[k] > maxForce * maxForce) if (Ft0[k] * Ft0[k] > maxForce * maxForce)
{ {
@ -610,8 +676,32 @@ void b3SpringCloth::Draw() const
const b3Mesh* m = m_mesh; const b3Mesh* m = m_mesh;
for (u32 i = 0; i < m->vertexCount; ++i) for (u32 i = 0; i < m->vertexCount; ++i)
{
b3MassContact* c = m_contacts + i;
if (c->lockN)
{ {
b3Draw_draw->DrawPoint(m_x[i], 6.0f, b3Color_green); b3Draw_draw->DrawPoint(m_x[i], 6.0f, b3Color_green);
b3Draw_draw->DrawSegment(m_x[i], m_x[i] + c->n, b3Color_yellow);
b3Draw_draw->DrawSegment(m_x[i], m_x[i] + c->t1, b3Color_yellow);
b3Draw_draw->DrawSegment(m_x[i], m_x[i] + c->t2, b3Color_yellow);
}
}
for (u32 i = 0; i < m_springCount; ++i)
{
b3Spring* s = m_springs + i;
b3Vec3 x1 = m_x[s->i1];
b3Vec3 x2 = m_x[s->i2];
if (s->type == e_strechSpring)
{
b3Draw_draw->DrawSegment(x1, x2, b3Color_black);
}
} }
for (u32 i = 0; i < m->triangleCount; ++i) for (u32 i = 0; i < m->triangleCount; ++i)
@ -622,8 +712,6 @@ void b3SpringCloth::Draw() const
b3Vec3 v2 = m_x[t->v2]; b3Vec3 v2 = m_x[t->v2];
b3Vec3 v3 = m_x[t->v3]; b3Vec3 v3 = m_x[t->v3];
b3Draw_draw->DrawTriangle(v1, v2, v3, b3Color_black);
b3Vec3 n1 = b3Cross(v2 - v1, v3 - v1); b3Vec3 n1 = b3Cross(v2 - v1, v3 - v1);
n1.Normalize(); n1.Normalize();
b3Draw_draw->DrawSolidTriangle(n1, v1, v2, v3, b3Color_blue); b3Draw_draw->DrawSolidTriangle(n1, v1, v2, v3, b3Color_blue);

View File

@ -492,9 +492,9 @@ void b3SpringSolver::Solve(b3DenseVec3& dv, b3DenseVec3& e, u32& iterations, con
B3_ASSERT(b3IsValid(deltaNew)); B3_ASSERT(b3IsValid(deltaNew));
// [0, 1] // [0, 1]
const float32 epsilon = 1000.0f * B3_EPSILON; const float32 epsilon = 10.0f * B3_EPSILON;
// Limit number of iterations to prevent cycling. // Maximum number of iterations.
const u32 maxIters = 1000; const u32 maxIters = 1000;
// Main iteration loop. // Main iteration loop.