346 lines
8.1 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>
struct b3ClothMesh;
struct b3ClothParticleDef;
class b3ClothParticle;
struct b3ForceDef;
class b3Force;
struct b3ClothSphereShapeDef;
class b3ClothSphereShape;
struct b3ClothCapsuleShapeDef;
class b3ClothCapsuleShape;
struct b3ClothTriangleShapeDef;
class b3ClothTriangleShape;
struct b3ClothWorldShapeDef;
class b3ClothWorldShape;
struct b3RayCastInput;
struct b3RayCastOutput;
struct b3ClothTimeStep;
struct b3ClothRayCastSingleOutput
{
b3ClothTriangleShape* triangle;
scalar fraction;
b3Vec3 normal;
};
// Cloth definition
// This requires defining a cloth mesh which is typically bound to a render mesh
// and some uniform parameters.
struct b3ClothDef
{
b3ClothDef()
{
mesh = nullptr;
density = scalar(0);
streching = scalar(0);
strechDamping = scalar(0);
shearing = scalar(0);
shearDamping = scalar(0);
bending = scalar(0);
bendDamping = scalar(0);
sewing = scalar(0);
sewDamping = scalar(0);
thickness = scalar(0);
friction = scalar(0.2);
}
// Cloth mesh
const b3ClothMesh* mesh;
// Cloth density in kg/m^2
scalar density;
// Streching stiffness
scalar streching;
// Strech damping stiffness
scalar strechDamping;
// Shearing stiffness
scalar shearing;
// Shear damping stiffness
scalar shearDamping;
// Bending stiffness
scalar bending;
// Bend damping stiffness
scalar bendDamping;
// Sewing stiffness
scalar sewing;
// Sew damping stiffness
scalar sewDamping;
// Shape thickness
scalar thickness;
// Shape coefficient of friction
scalar friction;
};
// A cloth represents a deformable surface as a collection of particles.
// Particles may be connected with each other by forces.
class b3Cloth
{
public:
b3Cloth();
b3Cloth(const b3ClothDef& def);
~b3Cloth();
// Create a particle.
b3ClothParticle* CreateParticle(const b3ClothParticleDef& def);
// Destroy a given particle.
void DestroyParticle(b3ClothParticle* particle);
// Return the list of particles in this cloth.
const b3List2<b3ClothParticle>& GetParticleList() const;
// Create a force.
b3Force* CreateForce(const b3ForceDef& def);
// Destroy a given force.
void DestroyForce(b3Force* force);
// Return the list of forces in this cloth.
const b3List2<b3Force>& GetForceList() const;
// Create a sphere shape.
b3ClothSphereShape* CreateSphereShape(const b3ClothSphereShapeDef& def);
// Destroy a given sphere shape.
void DestroySphereShape(b3ClothSphereShape* shape);
// Return the list of sphere shapes in this cloth.
const b3List2<b3ClothSphereShape>& GetSphereShapeList() const;
// Create a capsule shape.
b3ClothCapsuleShape* CreateCapsuleShape(const b3ClothCapsuleShapeDef& def);
// Destroy a given capsule shape.
void DestroyCapsuleShape(b3ClothCapsuleShape* shape);
// Return the list of capsule shapes in this cloth.
const b3List2<b3ClothCapsuleShape>& GetCapsuleShapeList() const;
// Create a triangle shape.
b3ClothTriangleShape* CreateTriangleShape(const b3ClothTriangleShapeDef& def);
// Destroy a given triangle shape.
void DestroyTriangleShape(b3ClothTriangleShape* shape);
// Return the list of triangle shapes in this cloth.
const b3List2<b3ClothTriangleShape>& GetTriangleShapeList() const;
// Create a new world shape.
b3ClothWorldShape* CreateWorldShape(const b3ClothWorldShapeDef& def);
// Destroy a given world shape.
void DestroyWorldShape(b3ClothWorldShape* shape);
// Return the list of world shapes in this cloth.
const b3List2<b3ClothWorldShape>& GetWorldShapeList() const;
// Set the acceleration of gravity.
void SetGravity(const b3Vec3& gravity);
// Get the acceleration of gravity.
b3Vec3 GetGravity() const;
// Perform a time step.
void Step(scalar dt, u32 velocityIterations, u32 positionIterations);
// Perform a ray cast with the cloth.
bool RayCastSingle(b3ClothRayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const;
// Get the cloth mesh.
const b3ClothMesh* GetMesh() const;
// Get mesh particle.
b3ClothParticle* GetParticle(u32 index);
// Get mesh sphere.
b3ClothSphereShape* GetSphere(u32 index);
// Get mesh triangle.
b3ClothTriangleShape* GetTriangle(u32 index);
// Enable or disable self-collision.
void EnableSelfCollision(bool flag);
// Is self-collision enabled?
bool IsSelfCollisionEnabled() const;
// Return the kinetic (or dynamic) energy in this system.
scalar GetEnergy() const;
// Debug draw the cloth entities.
void Draw() const;
private:
friend class b3ClothParticle;
friend class b3ClothSphereShape;
friend class b3ClothCapsuleShape;
friend class b3ClothTriangleShape;
friend class b3ClothWorldShape;
friend class b3ShearForce;
friend class b3StretchForce;
friend class b3SpringForce;
friend class b3MouseForce;
friend class b3ClothContactManager;
// Rest the mass data of the cloth.
void ResetMass();
// Solve
void Solve(const b3ClothTimeStep& step);
// Stack allocator
b3StackAllocator m_stackAllocator;
// Gravity acceleration
b3Vec3 m_gravity;
// Pool of particles
b3BlockPool m_particleBlocks;
// Pool of sphere shapes
b3BlockPool m_sphereShapeBlocks;
// Pool of capsule shapes
b3BlockPool m_capsuleShapeBlocks;
// Pool of triangle shapes
b3BlockPool m_triangleShapeBlocks;
// Pool of world shapes
b3BlockPool m_worldShapeBlocks;
// List of particles
b3List2<b3ClothParticle> m_particleList;
// List of forces
b3List2<b3Force> m_forceList;
// List of sphere shapes
b3List2<b3ClothSphereShape> m_sphereShapeList;
// List of capsule shapes
b3List2<b3ClothCapsuleShape> m_capsuleShapeList;
// List of triangle shapes
b3List2<b3ClothTriangleShape> m_triangleShapeList;
// List of world shapes
b3List2<b3ClothWorldShape> m_worldShapeList;
// Contact manager
b3ClothContactManager m_contactManager;
// Used to compute the time step ratio to
// support variable time steps.
scalar m_inv_dt0;
// Mesh
const b3ClothMesh* m_mesh;
// Mesh vertex particles
b3ClothParticle** m_particles;
// Mesh vertex sphere shapes
b3ClothSphereShape** m_spheres;
// Mesh triangle triangle shapes
b3ClothTriangleShape** m_triangles;
// Self-collision activation flag
bool m_enableSelfCollision;
};
inline void b3Cloth::SetGravity(const b3Vec3& gravity)
{
m_gravity = gravity;
}
inline b3Vec3 b3Cloth::GetGravity() const
{
return m_gravity;
}
inline bool b3Cloth::IsSelfCollisionEnabled() const
{
return m_enableSelfCollision;
}
inline const b3List2<b3Force>& b3Cloth::GetForceList() const
{
return m_forceList;
}
inline const b3List2<b3ClothParticle>& b3Cloth::GetParticleList() const
{
return m_particleList;
}
inline const b3List2<b3ClothSphereShape>& b3Cloth::GetSphereShapeList() const
{
return m_sphereShapeList;
}
inline const b3List2<b3ClothCapsuleShape>& b3Cloth::GetCapsuleShapeList() const
{
return m_capsuleShapeList;
}
inline const b3List2<b3ClothTriangleShape>& b3Cloth::GetTriangleShapeList() const
{
return m_triangleShapeList;
}
inline const b3List2<b3ClothWorldShape>& b3Cloth::GetWorldShapeList() const
{
return m_worldShapeList;
}
inline const b3ClothMesh* b3Cloth::GetMesh() const
{
return m_mesh;
}
#endif