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

@ -148,7 +148,7 @@ int main(int argc, char** args)
#if defined(_WIN32)
// Report memory leaks
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
//_CrtSetBreakAlloc(x);
//_CrtSetBreakAlloc(0);
#endif
if (glfwInit() == 0)

View File

@ -22,10 +22,8 @@
class ClothDragger
{
public:
ClothDragger(Ray3* ray, b3Cloth* cloth)
ClothDragger(Ray3* ray, b3Cloth*& cloth) : m_ray(ray), m_cloth(cloth)
{
m_ray = ray;
m_cloth = cloth;
m_isSelected = false;
}
@ -275,7 +273,7 @@ private:
Ray3* m_ray;
float32 m_x;
b3Cloth * m_cloth;
b3Cloth*& m_cloth;
u32 m_selection;
float32 m_u, m_v;
b3ParticleType m_t1, m_t2, m_t3;
@ -284,39 +282,29 @@ private:
class ClothTest : public Test
{
public:
ClothTest() : m_clothDragger(&m_clothRay, &m_cloth)
ClothTest() : m_clothDragger(&m_clothRay, m_cloth)
{
m_cloth.SetGravity(b3Vec3(0.0f, -10.0f, 0.0f));
m_world.SetGravity(b3Vec3(0.0f, -10.0f, 0.0f));
m_clothRay.origin.SetZero();
m_clothRay.direction.Set(0.0f, 0.0f, -1.0f);
m_clothRay.fraction = g_camera->m_zFar;
m_cloth = nullptr;
}
void Step()
{
float32 dt = g_testSettings->inv_hertz;
Test::Step();
m_cloth.Step(dt);
m_cloth.Apply();
m_cloth->Apply();
b3Shape** shapes = m_cloth.GetShapeList();
for (u32 i = 0; i < m_cloth.GetShapeCount(); ++i)
{
b3Shape* s = shapes[i];
b3Transform xf;
xf.SetIdentity();
g_draw->DrawSolidShape(s, b3Color_white, xf);
}
m_cloth.Draw();
m_cloth->Draw();
extern u32 b3_clothSolverIterations;
g_draw->DrawString(b3Color_white, "Iterations = %u", b3_clothSolverIterations);
float32 E = m_cloth.GetEnergy();
float32 E = m_cloth->GetEnergy();
g_draw->DrawString(b3Color_white, "E = %f", E);
if (m_clothDragger.IsSelected() == true)
@ -352,7 +340,7 @@ public:
}
Ray3 m_clothRay;
b3Cloth m_cloth;
b3Cloth* m_cloth;
ClothDragger m_clothDragger;
};

View File

@ -38,10 +38,10 @@ public:
void SetClothType(b3ParticleType type)
{
for (u32 i = 0; i < m_cloth.GetParticleCount(); ++i)
for (u32 i = 0; i < m_cloth->GetParticleCount(); ++i)
{
b3Particle* p = m_cloth.GetParticle(i);
m_cloth.SetType(p, type);
b3Particle* p = m_cloth->GetParticle(i);
m_cloth->SetType(p, type);
}
}
@ -62,9 +62,9 @@ public:
SetClothType(e_dynamicParticle);
}
for (u32 i = 0; i < m_cloth.GetParticleCount(); ++i)
for (u32 i = 0; i < m_cloth->GetParticleCount(); ++i)
{
b3Particle* p = m_cloth.GetParticle(i);
b3Particle* p = m_cloth->GetParticle(i);
b3Vec3 d;
d.SetZero();
@ -96,7 +96,7 @@ public:
{
if (p->type == e_staticParticle)
{
m_cloth.Translate(p, d);
m_cloth->Translate(p, d);
}
if (p->type == e_kinematicParticle)
@ -105,14 +105,14 @@ public:
v += 5.0f * d;
m_cloth.SetVelocity(p, d);
m_cloth->SetVelocity(p, d);
}
if (p->type == e_dynamicParticle)
{
b3Vec3 f = 100.0f * d;
m_cloth.ApplyForce(p, f);
m_cloth->ApplyForce(p, f);
}
}
}

View File

@ -49,18 +49,18 @@ public:
def.kd = 0.0f;
def.r = 0.05f;
m_cloth.Initialize(def);
m_cloth = m_world.CreateCloth(def);
b3AABB3 aabb;
aabb.m_lower.Set(-5.0f, -1.0f, -6.0f);
aabb.m_upper.Set(5.0f, 1.0f, -4.0f);
for (u32 i = 0; i < m_cloth.GetParticleCount(); ++i)
for (u32 i = 0; i < m_cloth->GetParticleCount(); ++i)
{
b3Particle* p = m_cloth.GetParticle(i);
b3Particle* p = m_cloth->GetParticle(i);
if (aabb.Contains(p->position))
{
m_cloth.SetType(p, e_staticParticle);
m_cloth->SetType(p, e_staticParticle);
}
}
}

View File

@ -62,7 +62,7 @@ public:
def.r = 0.2f;
def.ks = 10000.0f;
m_cloth.Initialize(def);
m_cloth = m_world.CreateCloth(def);
}
static Test* Create()

View File

@ -55,16 +55,26 @@ public:
def.kd = 0.0f;
def.r = 0.05f;
m_cloth.Initialize(def);
m_cloth = m_world.CreateCloth(def);
m_tableHull.SetAsCylinder(5.0f, 2.0f);
{
b3BodyDef bd;
bd.type = e_staticBody;
m_tableShape.m_hull = &m_tableHull;
m_tableShape.m_radius = 0.2f;
b3Body* b = m_world.CreateBody(bd);
m_tableShape.SetFriction(1.0f);
m_tableHull.SetAsCylinder(5.0f, 2.0f);
m_cloth.AddShape(&m_tableShape);
b3HullShape tableShape;
tableShape.m_hull = &m_tableHull;
tableShape.m_radius = 0.2f;
b3ShapeDef sd;
sd.shape = &tableShape;
sd.friction = 1.0f;
b->CreateShape(sd);
}
}
static Test* Create()
@ -77,7 +87,6 @@ public:
b3ClothMesh m_gridClothMesh;
b3QHull m_tableHull;
b3HullShape m_tableShape;
};
#endif

View File

@ -85,18 +85,18 @@ public:
def.kd = 0.0f;
def.r = 0.2f;
m_cloth.Initialize(def);
m_cloth = m_world.CreateCloth(def);
b3AABB3 aabb;
aabb.m_lower.Set(-5.0f, -1.0f, -6.0f);
aabb.m_upper.Set(5.0f, 1.0f, -4.0f);
for (u32 i = 0; i < m_cloth.GetParticleCount(); ++i)
for (u32 i = 0; i < m_cloth->GetParticleCount(); ++i)
{
b3Particle* p = m_cloth.GetParticle(i);
b3Particle* p = m_cloth->GetParticle(i);
if (aabb.Contains(p->position))
{
m_cloth.SetType(p, e_staticParticle);
m_cloth->SetType(p, e_staticParticle);
}
}
}
@ -105,25 +105,24 @@ public:
{
float32 dt = g_testSettings->inv_hertz;
m_cloth.Step(dt);
m_cloth.Apply();
m_cloth->Apply();
b3StackArray<b3Vec3, 256> tension;
tension.Resize(m_cloth.GetParticleCount());
tension.Resize(m_cloth->GetParticleCount());
for (u32 i = 0; i < tension.Count(); ++i)
{
tension[i].SetZero();
}
for (u32 i = 0; i < m_cloth.GetSpringCount(); ++i)
for (u32 i = 0; i < m_cloth->GetSpringCount(); ++i)
{
b3Spring* s = m_cloth.GetSpring(i);
b3Spring* s = m_cloth->GetSpring(i);
b3Particle* p1 = s->p1;
b3Particle* p2 = s->p2;
u32 i1 = m_cloth.GetParticleIndex(p1);
u32 i2 = m_cloth.GetParticleIndex(p2);
u32 i1 = m_cloth->GetParticleIndex(p1);
u32 i2 = m_cloth->GetParticleIndex(p2);
tension[i1] += s->tension;
tension[i2] -= s->tension;
@ -133,9 +132,9 @@ public:
{
b3ClothMeshTriangle* t = m_gridClothMesh.triangles + i;
b3Particle* p1 = m_cloth.GetParticle(t->v1);
b3Particle* p2 = m_cloth.GetParticle(t->v2);
b3Particle* p3 = m_cloth.GetParticle(t->v3);
b3Particle* p1 = m_cloth->GetParticle(t->v1);
b3Particle* p2 = m_cloth->GetParticle(t->v2);
b3Particle* p3 = m_cloth->GetParticle(t->v3);
b3Vec3 v1 = p1->position;
b3Vec3 v2 = p2->position;

View File

@ -19,13 +19,11 @@
#ifndef B3_CLOTH_H
#define B3_CLOTH_H
#include <bounce/common/math/mat33.h>
#include <bounce/common/template/array.h>
#include <bounce/common/memory/stack_allocator.h>
// Maximum number of shapes per cloth.
#define B3_CLOTH_SHAPE_CAPACITY 32
#include <bounce/common/math/transform.h>
#include <bounce/common/template/list.h>
class b3StackAllocator;
class b3World;
class b3Shape;
struct b3ClothMesh;
@ -157,8 +155,8 @@ struct b3Spring
void ApplyForces(const b3ClothSolverData* data);
};
// Read-only contact
struct b3ParticleContact
// Read-only body contact between a particle and a solid
struct b3BodyContact
{
b3Particle* p1;
b3Shape* s2;
@ -173,22 +171,13 @@ struct b3ParticleContact
class b3Cloth
{
public:
b3Cloth();
~b3Cloth();
// Initialize this cloth from a definition.
void Initialize(const b3ClothDef& def);
// Get the world the cloth belongs to.
const b3World* GetWorld() const;
b3World* GetWorld();
// Return the cloth mesh used to initialize this cloth.
b3ClothMesh* GetMesh() const;
// Set the gravitational acceleration applied to this cloth.
// Units are m/s^2.
void SetGravity(const b3Vec3& gravity);
// Return the gravitational acceleration applied to this cloth.
const b3Vec3& GetGravity() const;
// Return the number of particles in this cloth.
u32 GetParticleCount() const;
@ -220,26 +209,28 @@ public:
// Return the kinetic (or dynamic) energy in this system.
float32 GetEnergy() const;
// Add a collision shape to the list of shapes in this cloth.
// The cloth will be able to respond to collisions with each shape in the list of shapes.
// Current the shape will be treated as a static shape.
void AddShape(b3Shape* shape);
// Get the next cloth in the world cloth list.
const b3Cloth* GetNext() const;
// Return the number of collision shapes in this cloth.
u32 GetShapeCount() const;
// Return the list of collision shapes added to this cloth.
b3Shape** GetShapeList();
// Perform a time step.
void Step(float32 dt);
// Get the next cloth in the world cloth list.
b3Cloth* GetNext();
// Set the positions of the mesh vertices to the positions of their associated particles.
void Apply() const;
// Debug draw the cloth using the associated cloth mesh.
void Draw() const;
protected:
private:
friend class b3World;
friend class b3List2<b3Cloth>;
b3Cloth(const b3ClothDef& def, b3World* world);
~b3Cloth();
// Perform a time step. Called only inside b3World.
void Step(float32 dt, const b3Vec3& gravity);
// Compute mass of each particle.
void ResetMass();
@ -248,11 +239,12 @@ protected:
void UpdateContacts();
// Solve
void Solve(float32 dt);
void Solve(float32 dt, const b3Vec3& gravity);
b3StackAllocator m_allocator;
b3StackAllocator* m_allocator;
b3Vec3 m_gravity;
b3ClothMesh* m_mesh;
float32 m_density;
u32 m_particleCount;
b3Particle* m_particles;
@ -260,31 +252,32 @@ protected:
u32 m_springCount;
b3Spring* m_springs;
b3ParticleContact* m_contacts;
b3BodyContact* m_contacts;
//u32 m_contactCount;
b3Shape* m_shapes[B3_CLOTH_SHAPE_CAPACITY];
u32 m_shapeCount;
b3ClothMesh* m_mesh;
float32 m_density;
// The parent world of this cloth.
b3World* m_world;
// Links to the world cloth list.
b3Cloth* m_prev;
b3Cloth* m_next;
};
inline const b3World* b3Cloth::GetWorld() const
{
return m_world;
}
inline b3World* b3Cloth::GetWorld()
{
return m_world;
}
inline b3ClothMesh* b3Cloth::GetMesh() const
{
return m_mesh;
}
inline const b3Vec3& b3Cloth::GetGravity() const
{
return m_gravity;
}
inline void b3Cloth::SetGravity(const b3Vec3& gravity)
{
m_gravity = gravity;
}
inline u32 b3Cloth::GetParticleCount() const
{
return m_particleCount;
@ -368,14 +361,14 @@ inline float32 b3Cloth::GetEnergy() const
return 0.5f * E;
}
inline u32 b3Cloth::GetShapeCount() const
inline const b3Cloth* b3Cloth::GetNext() const
{
return m_shapeCount;
return m_next;
}
inline b3Shape** b3Cloth::GetShapeList()
inline b3Cloth* b3Cloth::GetNext()
{
return m_shapes;
return m_next;
}
#endif

View File

@ -28,7 +28,7 @@ struct b3SparseMat33;
struct b3Particle;
struct b3Spring;
struct b3ParticleContact;
struct b3BodyContact;
class b3Shape;
class b3StackAllocator;
@ -65,7 +65,7 @@ public:
void Add(b3Particle* p);
void Add(b3Spring* s);
void Add(b3ParticleContact* c);
void Add(b3BodyContact* c);
void Solve(float32 dt, const b3Vec3& gravity);
private:
@ -93,7 +93,7 @@ private:
u32 m_contactCapacity;
u32 m_contactCount;
b3ParticleContact** m_contacts;
b3BodyContact** m_contacts;
u32 m_constraintCapacity;
u32 m_constraintCount;

View File

@ -26,7 +26,10 @@
#include <bounce/dynamics/joint_manager.h>
#include <bounce/dynamics/contact_manager.h>
struct b3ClothDef;
struct b3BodyDef;
class b3Cloth;
class b3Body;
class b3QueryListener;
class b3RayCastListener;
@ -67,6 +70,12 @@ public:
// The acceleration has units of m/s^2.
void SetGravity(const b3Vec3& gravity);
// Create a new deformable cloth.
b3Cloth* CreateCloth(const b3ClothDef& def);
// Destroy an existing deformable cloth.
void DestroyCloth(b3Cloth* cloth);
// Create a new rigid body.
b3Body* CreateBody(const b3BodyDef& def);
@ -129,6 +138,7 @@ private :
e_clearForcesFlag = 0x0002,
};
friend class b3Cloth;
friend class b3Body;
friend class b3Shape;
friend class b3Contact;
@ -138,14 +148,20 @@ private :
void Solve(float32 dt, u32 velocityIterations, u32 positionIterations);
void StepCloth(float32 dt);
bool m_sleeping;
bool m_warmStarting;
u32 m_flags;
b3Vec3 m_gravity;
b3StackAllocator m_stackAllocator;
b3BlockPool m_clothBlocks;
b3BlockPool m_bodyBlocks;
// List of clothes
b3List2<b3Cloth> m_clothList;
// List of bodies
b3List2<b3Body> m_bodyList;

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)