238 lines
5.3 KiB
C++

/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_H
#define B3_CLOTH_H
#include <bounce/common/template/list.h>
#include <bounce/common/memory/stack_allocator.h>
#include <bounce/common/memory/block_pool.h>
#include <bounce/common/math/transform.h>
#include <bounce/cloth/cloth_contact_manager.h>
class b3World;
struct b3ParticleDef;
class b3Particle;
struct b3ForceDef;
class b3Force;
class b3ClothTriangle;
struct b3ClothMesh;
class b3RayCastListener;
struct b3RayCastInput;
struct b3RayCastOutput;
struct b3ClothRayCastSingleOutput
{
u32 triangle;
float32 fraction;
b3Vec3 normal;
};
// Cloth definition
// This requires defining a cloth mesh which is typically bound to a render mesh
struct b3ClothDef
{
b3ClothDef()
{
mesh = nullptr;
density = 0.0f;
streching = 0.0f;
sewing = 0.0f;
bending = 0.0f;
damping = 0.0f;
thickness = 0.0f;
friction = 0.2f;
}
// Cloth mesh
const b3ClothMesh* mesh;
// Cloth density in kg/m^2
float32 density;
// Streching stiffness
float32 streching;
// Bending stiffness
float32 bending;
// Sewing stiffness
float32 sewing;
// Damping stiffness
float32 damping;
// Cloth thickness
float32 thickness;
// Cloth coefficient of friction
float32 friction;
};
// A cloth represents a deformable surface as a collection of particles.
// Particles may be connected with each other by springs.
class b3Cloth
{
public:
b3Cloth(const b3ClothDef& def);
~b3Cloth();
// Set the acceleration of gravity.
void SetGravity(const b3Vec3& gravity);
// Get the acceleration of gravity.
b3Vec3 GetGravity() const;
// Attach a world to this cloth.
// The cloth will be able to respond to collisions with the rigid bodies in the attached world.
void SetWorld(b3World* world);
// Get the world attached to this cloth.
const b3World* GetWorld() const;
b3World* GetWorld();
// Create a particle.
b3Particle* CreateParticle(const b3ParticleDef& def);
// Destroy a given particle.
void DestroyParticle(b3Particle* particle);
// Create a force.
b3Force* CreateForce(const b3ForceDef& def);
// Destroy a given force.
void DestroyForce(b3Force* force);
// Perform a ray cast with the cloth.
bool RayCastSingle(b3ClothRayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const;
// Perform a ray cast with a given cloth mesh triangle.
bool RayCast(b3RayCastOutput* output, const b3RayCastInput* input, u32 triangleIndex) const;
// Return the cloth mesh proxy.
const b3ClothMesh* GetMesh() const;
// Return the cloth particle given the vertex index.
b3Particle* GetParticle(u32 i);
// Return the cloth triangle given the triangle index.
b3ClothTriangle* GetTriangle(u32 i);
// Return the list of particles in this cloth.
const b3List2<b3Particle>& GetParticleList() const;
// Return the list of forces in this cloth.
const b3List2<b3Force>& GetForceList() const;
// Return the kinetic (or dynamic) energy in this system.
float32 GetEnergy() const;
// Perform a time step.
void Step(float32 dt, u32 velocityIterations, u32 positionIterations);
// Debug draw the cloth using the associated cloth mesh.
void Draw() const;
private:
friend class b3Particle;
friend class b3ClothTriangle;
friend class b3StrechForce;
friend class b3SpringForce;
friend class b3ClothContactManager;
// Compute mass of each particle.
void ComputeMass();
// Solve
void Solve(float32 dt, const b3Vec3& gravity, u32 velocityIterations, u32 positionIterations);
// Stack allocator
b3StackAllocator m_stackAllocator;
// The world attached to this cloth
b3World* m_world;
// Gravity acceleration
b3Vec3 m_gravity;
// Proxy mesh
const b3ClothMesh* m_mesh;
// Particles
b3Particle** m_particles;
// Triangles
b3ClothTriangle* m_triangles;
// Cloth density
float32 m_density;
// Pool of particles
b3BlockPool m_particleBlocks;
// List of particles
b3List2<b3Particle> m_particleList;
// List of forces
b3List2<b3Force> m_forceList;
// Contact manager
b3ClothContactManager m_contactManager;
};
inline void b3Cloth::SetGravity(const b3Vec3& gravity)
{
m_gravity = gravity;
}
inline b3Vec3 b3Cloth::GetGravity() const
{
return m_gravity;
}
inline const b3World* b3Cloth::GetWorld() const
{
return m_world;
}
inline b3World* b3Cloth::GetWorld()
{
return m_world;
}
inline const b3ClothMesh* b3Cloth::GetMesh() const
{
return m_mesh;
}
inline const b3List2<b3Particle>& b3Cloth::GetParticleList() const
{
return m_particleList;
}
inline const b3List2<b3Force>& b3Cloth::GetForceList() const
{
return m_forceList;
}
#endif