now b3World is responsable for creating or destroying b3Cloth; clean up; update tests
This commit is contained in:
parent
8d2affb0b2
commit
43013ad80b
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user