now b3World is responsable for creating or destroying b3Cloth; clean up; update tests

This commit is contained in:
Irlan
2018-05-26 00:41:41 -03:00
parent 8d2affb0b2
commit 43013ad80b
13 changed files with 218 additions and 204 deletions

View File

@@ -22,6 +22,8 @@
#include <bounce/dynamics/cloth/sparse_mat33.h>
#include <bounce/dynamics/cloth/cloth_mesh.h>
#include <bounce/dynamics/shapes/shape.h>
#include <bounce/dynamics/body.h>
#include <bounce/dynamics/world.h>
#include <bounce/common/memory/stack_allocator.h>
#include <bounce/common/draw.h>
@@ -82,34 +84,6 @@ void b3Spring::ApplyForces(const b3ClothSolverData* data)
Jv = -kd * I;
}
// b3Cloth
b3Cloth::b3Cloth()
{
m_gravity.SetZero();
m_particleCount = 0;
m_particles = nullptr;
m_springs = nullptr;
m_springCount = 0;
m_contacts = nullptr;
//m_contactCount = 0;
m_shapeCount = 0;
m_mesh = nullptr;
m_gravity.SetZero();
}
b3Cloth::~b3Cloth()
{
b3Free(m_particles);
b3Free(m_springs);
b3Free(m_contacts);
}
static B3_FORCE_INLINE u32 b3NextIndex(u32 i)
{
return i + 1 < 3 ? i + 1 : 0;
@@ -228,20 +202,22 @@ static u32 b3FindSharedEdges(b3SharedEdge* sharedEdges, const b3ClothMesh* m)
return sharedCount;
}
void b3Cloth::Initialize(const b3ClothDef& def)
b3Cloth::b3Cloth(const b3ClothDef& def, b3World* world)
{
B3_ASSERT(def.mesh);
B3_ASSERT(def.density > 0.0f);
m_world = world;
m_allocator = &m_world->m_stackAllocator;
m_mesh = def.mesh;
m_density = def.density;
const b3ClothMesh* m = m_mesh;
b3ClothMesh* m = m_mesh;
// Create particles
m_particleCount = m->vertexCount;
m_particles = (b3Particle*)b3Alloc(m_particleCount * sizeof(b3Particle));
m_contacts = (b3ParticleContact*)b3Alloc(m_particleCount * sizeof(b3ParticleContact));
m_contacts = (b3BodyContact*)b3Alloc(m_particleCount * sizeof(b3BodyContact));
for (u32 i = 0; i < m_particleCount; ++i)
{
@@ -258,7 +234,7 @@ void b3Cloth::Initialize(const b3ClothDef& def)
p->translation.SetZero();
p->x.SetZero();
b3ParticleContact* c = m_contacts + i;
b3BodyContact* c = m_contacts + i;
c->n_active = false;
c->t1_active = false;
c->t2_active = false;
@@ -268,16 +244,18 @@ void b3Cloth::Initialize(const b3ClothDef& def)
ResetMass();
// Create springs
m_springCount = 0;
u32 edgeCount = 3 * m->triangleCount;
b3UniqueEdge* uniqueEdges = (b3UniqueEdge*)m_allocator.Allocate(edgeCount * sizeof(b3UniqueEdge));
b3UniqueEdge* uniqueEdges = (b3UniqueEdge*)m_allocator->Allocate(edgeCount * sizeof(b3UniqueEdge));
u32 uniqueCount = b3FindUniqueEdges(uniqueEdges, m);
u32 springCapacity = uniqueCount;
#if B3_CLOTH_BENDING
b3SharedEdge* sharedEdges = (b3SharedEdge*)m_allocator.Allocate(edgeCount * sizeof(b3SharedEdge));
b3SharedEdge* sharedEdges = (b3SharedEdge*)m_allocator->Allocate(edgeCount * sizeof(b3SharedEdge));
u32 sharedCount = b3FindSharedEdges(sharedEdges, m);
springCapacity += sharedCount;
@@ -332,10 +310,10 @@ void b3Cloth::Initialize(const b3ClothDef& def)
s->tension.SetZero();
}
m_allocator.Free(sharedEdges);
m_allocator->Free(sharedEdges);
#endif
m_allocator.Free(uniqueEdges);
m_allocator->Free(uniqueEdges);
// Sewing
for (u32 i = 0; i < m->sewingLineCount; ++i)
@@ -358,6 +336,13 @@ void b3Cloth::Initialize(const b3ClothDef& def)
B3_ASSERT(m_springCount <= springCapacity);
}
b3Cloth::~b3Cloth()
{
b3Free(m_particles);
b3Free(m_springs);
b3Free(m_contacts);
}
void b3Cloth::ResetMass()
{
for (u32 i = 0; i < m_particleCount; ++i)
@@ -399,18 +384,6 @@ void b3Cloth::ResetMass()
}
}
void b3Cloth::AddShape(b3Shape* shape)
{
B3_ASSERT(m_shapeCount < B3_CLOTH_SHAPE_CAPACITY);
if (m_shapeCount == B3_CLOTH_SHAPE_CAPACITY)
{
return;
}
m_shapes[m_shapeCount++] = shape;
}
void b3Cloth::UpdateContacts()
{
B3_PROFILE("Update Contacts");
@@ -428,16 +401,16 @@ void b3Cloth::UpdateContacts()
{
b3Particle* p = m_particles + i;
// Static particles can't participate in collisions.
// Static particles can't participate in unilateral collisions.
if (p->type == e_staticParticle)
{
continue;
}
b3ParticleContact* c = m_contacts + i;
b3BodyContact* c = m_contacts + i;
// Save the old contact
b3ParticleContact c0 = *c;
b3BodyContact c0 = *c;
b3Sphere s1;
s1.vertex = p->position;
@@ -446,39 +419,34 @@ void b3Cloth::UpdateContacts()
// Find the deepest penetration
float32 bestSeparation = 0.0f;
b3Vec3 bestNormal(0.0f, 0.0f, 0.0f);
u32 bestIndex = ~0;
b3Shape* bestShape = nullptr;
for (u32 j = 0; j < m_shapeCount; ++j)
for (b3Body* body = m_world->GetBodyList().m_head; body; body = body->GetNext())
{
b3Shape* s2 = m_shapes[j];
b3Transform xf2;
xf2.SetIdentity();
b3TestSphereOutput output;
if (s2->TestSphere(&output, s1, xf2) == false)
b3Transform xf = body->GetTransform();
for (b3Shape* shape = body->GetShapeList().m_head; shape; shape = shape->GetNext())
{
continue;
}
if (output.separation < bestSeparation)
{
bestSeparation = output.separation;
bestNormal = output.normal;
bestIndex = j;
b3TestSphereOutput output;
if (shape->TestSphere(&output, s1, xf))
{
if (output.separation < bestSeparation)
{
bestSeparation = output.separation;
bestNormal = output.normal;
bestShape = shape;
}
}
}
}
if (bestIndex != ~0)
if (bestShape != nullptr)
{
B3_ASSERT(bestSeparation <= 0.0f);
b3Shape* shape = m_shapes[bestIndex];
b3Shape* shape = bestShape;
float32 s = bestSeparation;
b3Vec3 n = bestNormal;
// Update contact manifold
// Remember the normal points from shape 2 to shape 1 (mass)
// Store the contact manifold
// Here the normal points from shape 2 to shape 1 (mass)
c->n_active = true;
c->p1 = p;
c->s2 = shape;
@@ -606,13 +574,13 @@ void b3Cloth::UpdateContacts()
}
void b3Cloth::Solve(float32 dt)
void b3Cloth::Solve(float32 dt, const b3Vec3& gravity)
{
B3_PROFILE("Solve");
// Solve
b3ClothSolverDef solverDef;
solverDef.stack = &m_allocator;
solverDef.stack = m_allocator;
solverDef.particleCapacity = m_particleCount;
solverDef.springCapacity = m_springCount;
solverDef.contactCapacity = m_particleCount;
@@ -638,7 +606,7 @@ void b3Cloth::Solve(float32 dt)
}
// Solve
solver.Solve(dt, m_gravity);
solver.Solve(dt, gravity);
// Clear external applied forces
for (u32 i = 0; i < m_particleCount; ++i)
@@ -653,7 +621,7 @@ void b3Cloth::Solve(float32 dt)
}
}
void b3Cloth::Step(float32 dt)
void b3Cloth::Step(float32 dt, const b3Vec3& gravity)
{
B3_PROFILE("Step");
@@ -663,7 +631,7 @@ void b3Cloth::Step(float32 dt)
// Solve constraints, integrate state, clear forces and translations.
if (dt > 0.0f)
{
Solve(dt);
Solve(dt, gravity);
}
}
@@ -696,7 +664,7 @@ void b3Cloth::Draw() const
b3Draw_draw->DrawPoint(p->position, 4.0f, b3Color_green);
}
b3ParticleContact* c = m_contacts + i;
b3BodyContact* c = m_contacts + i;
if (c->n_active)
{

View File

@@ -47,7 +47,7 @@ b3ClothSolver::b3ClothSolver(const b3ClothSolverDef& def)
m_contactCapacity = def.contactCapacity;
m_contactCount = 0;
m_contacts = (b3ParticleContact**)m_allocator->Allocate(m_contactCapacity * sizeof(b3ParticleContact*));
m_contacts = (b3BodyContact**)m_allocator->Allocate(m_contactCapacity * sizeof(b3BodyContact*));
m_constraintCapacity = def.particleCapacity;
m_constraintCount = 0;
@@ -68,7 +68,7 @@ void b3ClothSolver::Add(b3Particle* p)
m_particles[m_particleCount++] = p;
}
void b3ClothSolver::Add(b3ParticleContact* c)
void b3ClothSolver::Add(b3BodyContact* c)
{
m_contacts[m_contactCount++] = c;
}
@@ -95,7 +95,7 @@ void b3ClothSolver::InitializeConstraints()
for (u32 i = 0; i < m_contactCount; ++i)
{
b3ParticleContact* pc = m_contacts[i];
b3BodyContact* pc = m_contacts[i];
b3Particle* p = pc->p1;
B3_ASSERT(p->type != e_staticParticle);
@@ -179,10 +179,10 @@ void b3ClothSolver::Solve(float32 dt, const b3Vec3& gravity)
sx0[i] = p->x;
}
// Apply contact position corrections
// Apply contact position correction
for (u32 i = 0; i < m_contactCount; ++i)
{
b3ParticleContact* c = m_contacts[i];
b3BodyContact* c = m_contacts[i];
b3Particle* p = c->p1;
sy[p->solverId] -= c->s * c->n;
}
@@ -265,7 +265,7 @@ void b3ClothSolver::Solve(float32 dt, const b3Vec3& gravity)
// These forces can be used in contact constraint logic.
for (u32 i = 0; i < m_contactCount; ++i)
{
b3ParticleContact* c = m_contacts[i];
b3BodyContact* c = m_contacts[i];
b3Particle* p = c->p1;
b3Vec3 force = f[p->solverId];

View File

@@ -17,6 +17,7 @@
*/
#include <bounce/dynamics/world.h>
#include <bounce/dynamics/cloth/cloth.h>
#include <bounce/dynamics/body.h>
#include <bounce/dynamics/island.h>
#include <bounce/dynamics/world_listeners.h>
@@ -30,7 +31,9 @@ extern u32 b3_convexCalls, b3_convexCacheHits;
extern u32 b3_gjkCalls, b3_gjkIters, b3_gjkMaxIters;
extern bool b3_convexCache;
b3World::b3World() : m_bodyBlocks(sizeof(b3Body))
b3World::b3World() :
m_clothBlocks(sizeof(b3Cloth)),
m_bodyBlocks(sizeof(b3Body))
{
b3_allocCalls = 0;
b3_maxAllocCalls = 0;
@@ -51,6 +54,14 @@ b3World::b3World() : m_bodyBlocks(sizeof(b3Body))
b3World::~b3World()
{
b3Cloth* c = m_clothList.m_head;
while (c)
{
b3Cloth* c0 = c;
c = c->m_next;
c0->~b3Cloth();
}
b3Body* b = m_bodyList.m_head;
while (b)
{
@@ -82,6 +93,21 @@ void b3World::SetSleeping(bool flag)
}
}
b3Cloth* b3World::CreateCloth(const b3ClothDef& def)
{
void* mem = m_clothBlocks.Allocate();
b3Cloth* c = new(mem) b3Cloth(def, this);
m_clothList.PushFront(c);
return c;
}
void b3World::DestroyCloth(b3Cloth* c)
{
m_clothList.Remove(c);
c->~b3Cloth();
m_clothBlocks.Free(c);
}
b3Body* b3World::CreateBody(const b3BodyDef& def)
{
void* mem = m_bodyBlocks.Allocate();
@@ -142,6 +168,9 @@ void b3World::Step(float32 dt, u32 velocityIterations, u32 positionIterations)
}
//SolveTOI
// Step cloth dynamics
StepCloth(dt);
}
void b3World::Solve(float32 dt, u32 velocityIterations, u32 positionIterations)
@@ -337,6 +366,18 @@ void b3World::Solve(float32 dt, u32 velocityIterations, u32 positionIterations)
}
}
void b3World::StepCloth(float32 dt)
{
B3_PROFILE("Step Cloth");
b3Cloth* c = m_clothList.m_head;
while (c)
{
c->Step(dt, m_gravity);
c = c->GetNext();
}
}
struct b3RayCastCallback
{
float32 Report(const b3RayCastInput& input, u32 proxyId)