From 43013ad80b2d02334aff8abffc05e1317aedeeb5 Mon Sep 17 00:00:00 2001 From: Irlan <-> Date: Sat, 26 May 2018 00:41:41 -0300 Subject: [PATCH] now b3World is responsable for creating or destroying b3Cloth; clean up; update tests --- examples/testbed/framework/main.cpp | 2 +- examples/testbed/tests/cloth_test.h | 34 ++--- examples/testbed/tests/particle_types.h | 16 +-- examples/testbed/tests/pinned_cloth.h | 8 +- examples/testbed/tests/shirt.h | 2 +- examples/testbed/tests/table_cloth.h | 23 +++- examples/testbed/tests/tension_mapping.h | 27 ++-- include/bounce/dynamics/cloth/cloth.h | 105 +++++++-------- include/bounce/dynamics/cloth/cloth_solver.h | 6 +- include/bounce/dynamics/world.h | 16 +++ src/bounce/dynamics/cloth/cloth.cpp | 128 +++++++------------ src/bounce/dynamics/cloth/cloth_solver.cpp | 12 +- src/bounce/dynamics/world.cpp | 43 ++++++- 13 files changed, 218 insertions(+), 204 deletions(-) diff --git a/examples/testbed/framework/main.cpp b/examples/testbed/framework/main.cpp index c338850..211d510 100644 --- a/examples/testbed/framework/main.cpp +++ b/examples/testbed/framework/main.cpp @@ -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) diff --git a/examples/testbed/tests/cloth_test.h b/examples/testbed/tests/cloth_test.h index 517b1fe..ba6dfbf 100644 --- a/examples/testbed/tests/cloth_test.h +++ b/examples/testbed/tests/cloth_test.h @@ -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; }; diff --git a/examples/testbed/tests/particle_types.h b/examples/testbed/tests/particle_types.h index 48afdb9..dc45e6c 100644 --- a/examples/testbed/tests/particle_types.h +++ b/examples/testbed/tests/particle_types.h @@ -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); } } } diff --git a/examples/testbed/tests/pinned_cloth.h b/examples/testbed/tests/pinned_cloth.h index f1d3ffa..a9bf9cf 100644 --- a/examples/testbed/tests/pinned_cloth.h +++ b/examples/testbed/tests/pinned_cloth.h @@ -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); } } } diff --git a/examples/testbed/tests/shirt.h b/examples/testbed/tests/shirt.h index 784b42e..ed0a6c2 100644 --- a/examples/testbed/tests/shirt.h +++ b/examples/testbed/tests/shirt.h @@ -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() diff --git a/examples/testbed/tests/table_cloth.h b/examples/testbed/tests/table_cloth.h index e204c04..94a8506 100644 --- a/examples/testbed/tests/table_cloth.h +++ b/examples/testbed/tests/table_cloth.h @@ -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 \ No newline at end of file diff --git a/examples/testbed/tests/tension_mapping.h b/examples/testbed/tests/tension_mapping.h index ac8617d..befebef 100644 --- a/examples/testbed/tests/tension_mapping.h +++ b/examples/testbed/tests/tension_mapping.h @@ -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 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; diff --git a/include/bounce/dynamics/cloth/cloth.h b/include/bounce/dynamics/cloth/cloth.h index 20dca0e..6865d5f 100644 --- a/include/bounce/dynamics/cloth/cloth.h +++ b/include/bounce/dynamics/cloth/cloth.h @@ -19,13 +19,11 @@ #ifndef B3_CLOTH_H #define B3_CLOTH_H -#include -#include -#include - -// Maximum number of shapes per cloth. -#define B3_CLOTH_SHAPE_CAPACITY 32 +#include +#include +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(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 \ No newline at end of file diff --git a/include/bounce/dynamics/cloth/cloth_solver.h b/include/bounce/dynamics/cloth/cloth_solver.h index 52b7181..0d889ad 100644 --- a/include/bounce/dynamics/cloth/cloth_solver.h +++ b/include/bounce/dynamics/cloth/cloth_solver.h @@ -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; diff --git a/include/bounce/dynamics/world.h b/include/bounce/dynamics/world.h index 3251875..7228c00 100644 --- a/include/bounce/dynamics/world.h +++ b/include/bounce/dynamics/world.h @@ -26,7 +26,10 @@ #include #include +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 m_clothList; + // List of bodies b3List2 m_bodyList; diff --git a/src/bounce/dynamics/cloth/cloth.cpp b/src/bounce/dynamics/cloth/cloth.cpp index 160c723..91de182 100644 --- a/src/bounce/dynamics/cloth/cloth.cpp +++ b/src/bounce/dynamics/cloth/cloth.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -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) { diff --git a/src/bounce/dynamics/cloth/cloth_solver.cpp b/src/bounce/dynamics/cloth/cloth_solver.cpp index 597bc31..7c0ff8b 100644 --- a/src/bounce/dynamics/cloth/cloth_solver.cpp +++ b/src/bounce/dynamics/cloth/cloth_solver.cpp @@ -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]; diff --git a/src/bounce/dynamics/world.cpp b/src/bounce/dynamics/world.cpp index a0e940a..5ccb474 100644 --- a/src/bounce/dynamics/world.cpp +++ b/src/bounce/dynamics/world.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -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)