Organize cloth contacts
This commit is contained in:
parent
6b92664c1e
commit
f7becc7ee7
64
include/bounce/cloth/cloth_contact.h
Normal file
64
include/bounce/cloth/cloth_contact.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef B3_CLOTH_CONTACT_H
|
||||
#define B3_CLOTH_CONTACT_H
|
||||
|
||||
#include <bounce/common/template/list.h>
|
||||
|
||||
class b3Particle;
|
||||
struct b3ClothMeshTriangle;
|
||||
struct b3ClothAABBProxy;
|
||||
|
||||
// Contact between particle and a triangle
|
||||
class b3ParticleTriangleContact
|
||||
{
|
||||
public:
|
||||
private:
|
||||
friend class b3Cloth;
|
||||
friend class b3Particle;
|
||||
friend class b3ClothContactManager;
|
||||
friend class b3List2<b3ParticleTriangleContact>;
|
||||
friend class b3ClothContactSolver;
|
||||
|
||||
b3ParticleTriangleContact() { }
|
||||
~b3ParticleTriangleContact() { }
|
||||
|
||||
void Update();
|
||||
|
||||
// Particle
|
||||
b3Particle* m_p1;
|
||||
|
||||
// Triangle
|
||||
b3ClothMeshTriangle* m_triangle;
|
||||
b3ClothAABBProxy* m_triangleProxy;
|
||||
b3Particle* m_p2;
|
||||
b3Particle* m_p3;
|
||||
b3Particle* m_p4;
|
||||
|
||||
float32 m_normalImpulse;
|
||||
|
||||
bool m_front;
|
||||
|
||||
bool m_active;
|
||||
|
||||
b3ParticleTriangleContact* m_prev;
|
||||
b3ParticleTriangleContact* m_next;
|
||||
};
|
||||
|
||||
#endif
|
@ -19,36 +19,12 @@
|
||||
#ifndef B3_CLOTH_CONTACT_MANAGER_H
|
||||
#define B3_CLOTH_CONTACT_MANAGER_H
|
||||
|
||||
#include <bounce/cloth/cloth_contact.h>
|
||||
#include <bounce/collision/broad_phase.h>
|
||||
#include <bounce/common/memory/block_pool.h>
|
||||
#include <bounce/common/template/list.h>
|
||||
#include <bounce/collision/broad_phase.h>
|
||||
|
||||
class b3Cloth;
|
||||
class b3Particle;
|
||||
struct b3ClothMeshTriangle;
|
||||
struct b3ClothAABBProxy;
|
||||
|
||||
// Contact between particle and a triangle
|
||||
class b3ParticleTriangleContact
|
||||
{
|
||||
public:
|
||||
b3Particle* m_p1;
|
||||
|
||||
b3ClothMeshTriangle* m_triangle;
|
||||
b3ClothAABBProxy* m_triangleProxy;
|
||||
b3Particle* m_p2;
|
||||
b3Particle* m_p3;
|
||||
b3Particle* m_p4;
|
||||
|
||||
bool m_front;
|
||||
|
||||
bool m_active;
|
||||
|
||||
float32 m_normalImpulse;
|
||||
|
||||
b3ParticleTriangleContact* m_prev;
|
||||
b3ParticleTriangleContact* m_next;
|
||||
};
|
||||
|
||||
// Contact delegator for b3Cloth.
|
||||
class b3ClothContactManager
|
||||
@ -62,19 +38,14 @@ public:
|
||||
void FindNewContacts();
|
||||
|
||||
void UpdateContacts();
|
||||
|
||||
b3ParticleTriangleContact* Create();
|
||||
|
||||
|
||||
b3ParticleTriangleContact* CreateParticleTriangleContact();
|
||||
void Destroy(b3ParticleTriangleContact* c);
|
||||
|
||||
void Update(b3ParticleTriangleContact* c);
|
||||
|
||||
b3Cloth* m_cloth;
|
||||
|
||||
b3BlockPool m_particleTriangleContactBlocks;
|
||||
|
||||
b3Cloth* m_cloth;
|
||||
b3BroadPhase m_broadPhase;
|
||||
|
||||
b3List2<b3ParticleTriangleContact> m_particleTriangleContactList;
|
||||
};
|
||||
|
||||
|
@ -19,10 +19,10 @@
|
||||
#ifndef B3_PARTICLE_H
|
||||
#define B3_PARTICLE_H
|
||||
|
||||
#include <bounce/cloth/force.h>
|
||||
#include <bounce/common/math/transform.h>
|
||||
#include <bounce/common/math/vec2.h>
|
||||
#include <bounce/common/template/list.h>
|
||||
#include <bounce/cloth/force.h>
|
||||
|
||||
class b3Shape;
|
||||
class b3Cloth;
|
||||
@ -91,12 +91,14 @@ struct b3ParticleBodyContactWorldPoint
|
||||
float32 separation;
|
||||
};
|
||||
|
||||
// Cloth primitive type
|
||||
enum b3ClothAABBProxyType
|
||||
{
|
||||
e_particleProxy,
|
||||
e_triangleProxy
|
||||
};
|
||||
|
||||
// Cloth primitive broadphase proxy
|
||||
struct b3ClothAABBProxy
|
||||
{
|
||||
b3ClothAABBProxyType type;
|
||||
@ -160,6 +162,7 @@ private:
|
||||
friend class b3Cloth;
|
||||
friend class b3ClothSolver;
|
||||
friend class b3ClothContactManager;
|
||||
friend class b3ParticleTriangleContact;
|
||||
friend class b3ClothContactSolver;
|
||||
friend class b3Force;
|
||||
friend class b3SpringForce;
|
||||
@ -226,10 +229,8 @@ private:
|
||||
// AABB Proxy
|
||||
b3ClothAABBProxy m_aabbProxy;
|
||||
|
||||
//
|
||||
// Links to the cloth particle list.
|
||||
b3Particle* m_prev;
|
||||
|
||||
//
|
||||
b3Particle* m_next;
|
||||
};
|
||||
|
||||
|
183
src/bounce/cloth/cloth_contact.cpp
Normal file
183
src/bounce/cloth/cloth_contact.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <bounce/cloth/cloth_contact.h>
|
||||
#include <bounce/cloth/cloth_mesh.h>
|
||||
#include <bounce/cloth/particle.h>
|
||||
#include <bounce/common/geometry.h>
|
||||
|
||||
//
|
||||
static void b3Solve3(float32 out[3],
|
||||
const b3Vec3& A, const b3Vec3& B, const b3Vec3& C,
|
||||
const b3Vec3& Q)
|
||||
{
|
||||
// Test vertex regions
|
||||
float32 wAB[3], wBC[3], wCA[3];
|
||||
b3BarycentricCoordinates(wAB, A, B, Q);
|
||||
b3BarycentricCoordinates(wBC, B, C, Q);
|
||||
b3BarycentricCoordinates(wCA, C, A, Q);
|
||||
|
||||
// R A
|
||||
if (wAB[1] <= 0.0f && wCA[0] <= 0.0f)
|
||||
{
|
||||
out[0] = 1.0f;
|
||||
out[1] = 0.0f;
|
||||
out[2] = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// R B
|
||||
if (wAB[0] <= 0.0f && wBC[1] <= 0.0f)
|
||||
{
|
||||
out[0] = 0.0f;
|
||||
out[1] = 1.0f;
|
||||
out[2] = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// R C
|
||||
if (wBC[0] <= 0.0f && wCA[1] <= 0.0f)
|
||||
{
|
||||
out[0] = 0.0f;
|
||||
out[1] = 0.0f;
|
||||
out[2] = 1.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// Test edge regions
|
||||
float32 wABC[4];
|
||||
b3BarycentricCoordinates(wABC, A, B, C, Q);
|
||||
|
||||
// R AB
|
||||
if (wAB[0] > 0.0f && wAB[1] > 0.0f && wABC[3] * wABC[2] <= 0.0f)
|
||||
{
|
||||
float32 divisor = wAB[2];
|
||||
B3_ASSERT(divisor > 0.0f);
|
||||
float32 s = 1.0f / divisor;
|
||||
out[0] = s * wAB[0];
|
||||
out[1] = s * wAB[1];
|
||||
out[2] = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// R BC
|
||||
if (wBC[0] > 0.0f && wBC[1] > 0.0f && wABC[3] * wABC[0] <= 0.0f)
|
||||
{
|
||||
float32 divisor = wBC[2];
|
||||
B3_ASSERT(divisor > 0.0f);
|
||||
float32 s = 1.0f / divisor;
|
||||
out[0] = 0.0f;
|
||||
out[1] = s * wBC[0];
|
||||
out[2] = s * wBC[1];
|
||||
return;
|
||||
}
|
||||
|
||||
// R CA
|
||||
if (wCA[0] > 0.0f && wCA[1] > 0.0f && wABC[3] * wABC[1] <= 0.0f)
|
||||
{
|
||||
float32 divisor = wCA[2];
|
||||
B3_ASSERT(divisor > 0.0f);
|
||||
float32 s = 1.0f / divisor;
|
||||
out[0] = s * wCA[1];
|
||||
out[1] = 0.0f;
|
||||
out[2] = s * wCA[0];
|
||||
return;
|
||||
}
|
||||
|
||||
// R ABC/ACB
|
||||
float32 divisor = wABC[3];
|
||||
if (divisor == 0.0f)
|
||||
{
|
||||
float32 s = 1.0f / 3.0f;
|
||||
out[0] = s;
|
||||
out[1] = s;
|
||||
out[2] = s;
|
||||
return;
|
||||
}
|
||||
|
||||
B3_ASSERT(divisor > 0.0f);
|
||||
float32 s = 1.0f / divisor;
|
||||
out[0] = s * wABC[0];
|
||||
out[1] = s * wABC[1];
|
||||
out[2] = s * wABC[2];
|
||||
}
|
||||
|
||||
void b3ParticleTriangleContact::Update()
|
||||
{
|
||||
b3Vec3 A = m_p2->m_position;
|
||||
b3Vec3 B = m_p3->m_position;
|
||||
b3Vec3 C = m_p4->m_position;
|
||||
|
||||
b3Vec3 N = b3Cross(B - A, C - A);
|
||||
float32 len = N.Normalize();
|
||||
|
||||
// Is ABC degenerate?
|
||||
if (len == 0.0f)
|
||||
{
|
||||
m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
float32 r1 = m_p1->m_radius;
|
||||
float32 r2 = 0.0f;
|
||||
|
||||
float32 totalRadius = r1 + r2;
|
||||
|
||||
b3Vec3 P1 = m_p1->m_position;
|
||||
|
||||
float32 distance = b3Dot(N, P1 - A);
|
||||
|
||||
// Is P1 below the plane?
|
||||
if (distance < -totalRadius)
|
||||
{
|
||||
m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Is P1 above the plane?
|
||||
if (distance > totalRadius)
|
||||
{
|
||||
m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Closest point on ABC to P1
|
||||
float32 wABC[3];
|
||||
b3Solve3(wABC, A, B, C, P1);
|
||||
|
||||
b3Vec3 P2 = wABC[0] * A + wABC[1] * B + wABC[2] * C;
|
||||
|
||||
if (b3DistanceSquared(P1, P2) > totalRadius * totalRadius)
|
||||
{
|
||||
m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Activate the contact
|
||||
m_active = true;
|
||||
|
||||
// Is P1 in front or back of the plane?
|
||||
if (distance >= 0.0f)
|
||||
{
|
||||
m_front = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_front = false;
|
||||
}
|
||||
}
|
@ -93,26 +93,23 @@ void b3ClothContactManager::AddPair(void* data1, void* data2)
|
||||
}
|
||||
|
||||
// Create a new contact.
|
||||
b3ParticleTriangleContact* c = Create();
|
||||
b3ParticleTriangleContact* c = CreateParticleTriangleContact();
|
||||
|
||||
c->m_p1 = p1;
|
||||
|
||||
c->m_triangle = triangle;
|
||||
c->m_triangleProxy = proxy2;
|
||||
c->m_p2 = p2;
|
||||
c->m_p3 = p3;
|
||||
c->m_p4 = p4;
|
||||
c->m_triangle = triangle;
|
||||
c->m_triangleProxy = proxy2;
|
||||
|
||||
c->m_normalImpulse = 0.0f;
|
||||
c->m_front = false;
|
||||
c->m_active = false;
|
||||
|
||||
c->m_normalImpulse = 0.0f;
|
||||
|
||||
// Add the contact to the cloth contact list.
|
||||
m_particleTriangleContactList.PushFront(c);
|
||||
}
|
||||
|
||||
b3ParticleTriangleContact* b3ClothContactManager::Create()
|
||||
b3ParticleTriangleContact* b3ClothContactManager::CreateParticleTriangleContact()
|
||||
{
|
||||
void* block = m_particleTriangleContactBlocks.Allocate();
|
||||
return new(block) b3ParticleTriangleContact();
|
||||
@ -127,177 +124,11 @@ void b3ClothContactManager::Destroy(b3ParticleTriangleContact* c)
|
||||
m_particleTriangleContactBlocks.Free(c);
|
||||
}
|
||||
|
||||
static void b3Solve3(float32 out[3],
|
||||
const b3Vec3& A, const b3Vec3& B, const b3Vec3& C,
|
||||
const b3Vec3& Q)
|
||||
{
|
||||
// Test vertex regions
|
||||
float32 wAB[3], wBC[3], wCA[3];
|
||||
b3BarycentricCoordinates(wAB, A, B, Q);
|
||||
b3BarycentricCoordinates(wBC, B, C, Q);
|
||||
b3BarycentricCoordinates(wCA, C, A, Q);
|
||||
|
||||
// R A
|
||||
if (wAB[1] <= 0.0f && wCA[0] <= 0.0f)
|
||||
{
|
||||
out[0] = 1.0f;
|
||||
out[1] = 0.0f;
|
||||
out[2] = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// R B
|
||||
if (wAB[0] <= 0.0f && wBC[1] <= 0.0f)
|
||||
{
|
||||
out[0] = 0.0f;
|
||||
out[1] = 1.0f;
|
||||
out[2] = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// R C
|
||||
if (wBC[0] <= 0.0f && wCA[1] <= 0.0f)
|
||||
{
|
||||
out[0] = 0.0f;
|
||||
out[1] = 0.0f;
|
||||
out[2] = 1.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// Test edge regions
|
||||
float32 wABC[4];
|
||||
b3BarycentricCoordinates(wABC, A, B, C, Q);
|
||||
|
||||
// R AB
|
||||
if (wAB[0] > 0.0f && wAB[1] > 0.0f && wABC[3] * wABC[2] <= 0.0f)
|
||||
{
|
||||
float32 divisor = wAB[2];
|
||||
B3_ASSERT(divisor > 0.0f);
|
||||
float32 s = 1.0f / divisor;
|
||||
out[0] = s * wAB[0];
|
||||
out[1] = s * wAB[1];
|
||||
out[2] = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// R BC
|
||||
if (wBC[0] > 0.0f && wBC[1] > 0.0f && wABC[3] * wABC[0] <= 0.0f)
|
||||
{
|
||||
float32 divisor = wBC[2];
|
||||
B3_ASSERT(divisor > 0.0f);
|
||||
float32 s = 1.0f / divisor;
|
||||
out[0] = 0.0f;
|
||||
out[1] = s * wBC[0];
|
||||
out[2] = s * wBC[1];
|
||||
return;
|
||||
}
|
||||
|
||||
// R CA
|
||||
if (wCA[0] > 0.0f && wCA[1] > 0.0f && wABC[3] * wABC[1] <= 0.0f)
|
||||
{
|
||||
float32 divisor = wCA[2];
|
||||
B3_ASSERT(divisor > 0.0f);
|
||||
float32 s = 1.0f / divisor;
|
||||
out[0] = s * wCA[1];
|
||||
out[1] = 0.0f;
|
||||
out[2] = s * wCA[0];
|
||||
return;
|
||||
}
|
||||
|
||||
// R ABC/ACB
|
||||
float32 divisor = wABC[3];
|
||||
if (divisor == 0.0f)
|
||||
{
|
||||
float32 s = 1.0f / 3.0f;
|
||||
out[0] = s;
|
||||
out[1] = s;
|
||||
out[2] = s;
|
||||
return;
|
||||
}
|
||||
|
||||
B3_ASSERT(divisor > 0.0f);
|
||||
float32 s = 1.0f / divisor;
|
||||
out[0] = s * wABC[0];
|
||||
out[1] = s * wABC[1];
|
||||
out[2] = s * wABC[2];
|
||||
}
|
||||
|
||||
void b3ClothContactManager::Update(b3ParticleTriangleContact* c)
|
||||
{
|
||||
b3Particle* p1 = c->m_p1;
|
||||
|
||||
b3Particle* p2 = c->m_p2;
|
||||
b3Particle* p3 = c->m_p3;
|
||||
b3Particle* p4 = c->m_p4;
|
||||
|
||||
float32 r1 = p1->m_radius;
|
||||
float32 r2 = 0.0f;
|
||||
|
||||
float32 totalRadius = r1 + r2;
|
||||
|
||||
b3Vec3 A = p2->m_position;
|
||||
b3Vec3 B = p3->m_position;
|
||||
b3Vec3 C = p4->m_position;
|
||||
|
||||
b3Vec3 n = b3Cross(B - A, C - A);
|
||||
float32 len = n.Normalize();
|
||||
|
||||
// Is ABC degenerate?
|
||||
if (len == 0.0f)
|
||||
{
|
||||
c->m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
b3Vec3 P1 = p1->m_position;
|
||||
|
||||
float32 distance = b3Dot(n, P1 - A);
|
||||
|
||||
// Is P1 below the plane?
|
||||
if (distance < -totalRadius)
|
||||
{
|
||||
c->m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Is P1 above the plane?
|
||||
if (distance > totalRadius)
|
||||
{
|
||||
c->m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Closest point on ABC to P1
|
||||
float32 wABC[3];
|
||||
b3Solve3(wABC, A, B, C, P1);
|
||||
|
||||
b3Vec3 P2 = wABC[0] * A + wABC[1] * B + wABC[2] * C;
|
||||
|
||||
if (b3DistanceSquared(P1, P2) > totalRadius * totalRadius)
|
||||
{
|
||||
c->m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Activate the contact
|
||||
c->m_active = true;
|
||||
|
||||
// Is the the other point in front of the plane?
|
||||
if (distance >= 0.0f)
|
||||
{
|
||||
c->m_front = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->m_front = false;
|
||||
}
|
||||
}
|
||||
|
||||
void b3ClothContactManager::UpdateContacts()
|
||||
{
|
||||
B3_PROFILE("Cloth Update Contacts");
|
||||
|
||||
// Update the state of all triangle contacts.
|
||||
// Update the state of particle-triangle contacts.
|
||||
b3ParticleTriangleContact* c = m_particleTriangleContactList.m_head;
|
||||
while (c)
|
||||
{
|
||||
@ -327,7 +158,7 @@ void b3ClothContactManager::UpdateContacts()
|
||||
}
|
||||
|
||||
// The contact persists.
|
||||
Update(c);
|
||||
c->Update();
|
||||
|
||||
c = c->m_next;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user