now b3World is responsable for creating or destroying b3Cloth; clean up; update tests
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
@@ -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];
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user