refactor cloth
This commit is contained in:
		| @@ -19,117 +19,324 @@ | ||||
| #ifndef B3_CLOTH_H | ||||
| #define B3_CLOTH_H | ||||
|  | ||||
| #include <bounce/common/math/vec3.h> | ||||
| #include <bounce/collision/collision.h> | ||||
| #include <bounce/common/math/mat33.h> | ||||
| #include <bounce/common/template/array.h> | ||||
| #include <bounce/common/memory/stack_allocator.h> | ||||
|  | ||||
| struct b3Mesh; | ||||
| // Maximum number of shapes per cloth. | ||||
| #define B3_CLOTH_SHAPE_CAPACITY 32 | ||||
|  | ||||
| class b3Shape; | ||||
|  | ||||
| struct b3ClothMesh; | ||||
|  | ||||
| // Cloth mesh definition | ||||
| struct b3ClothDef | ||||
| { | ||||
| 	b3ClothDef() | ||||
| 	{ | ||||
| 		mesh = NULL; | ||||
| 		mesh = nullptr; | ||||
| 		density = 0.0f; | ||||
| 		gravity.SetZero(); | ||||
| 		k1 = 0.9f; | ||||
| 		k2 = 0.2f; | ||||
| 		kd = 0.1f; | ||||
| 		r = 0.0f; | ||||
| 		r = 0.05f; | ||||
| 		ks = 0.0f; | ||||
| 		kb = 0.0f; | ||||
| 		kd = 0.0f; | ||||
| 	} | ||||
|  | ||||
| 	// Cloth mesh | ||||
| 	// Each edge must be shared by at most two triangles (manifold) | ||||
| 	const b3Mesh* mesh; | ||||
| 	// Cloth proxy mesh  | ||||
| 	b3ClothMesh* mesh; | ||||
|  | ||||
| 	// Cloth density in kilograms per meter squared | ||||
| 	// Radius | ||||
| 	// This should be a small value. It can be used for correcting visual artifacts when  | ||||
| 	// the masses are colliding against a solid. | ||||
| 	float32 r; | ||||
|  | ||||
| 	// Cloth density in kg/m^3 | ||||
| 	float32 density; | ||||
|  | ||||
| 	// Gravity force | ||||
| 	b3Vec3 gravity; | ||||
|  | ||||
| 	// Streching stiffness | ||||
| 	float32 k1; | ||||
| 	float32 ks; | ||||
|  | ||||
| 	// Bending stiffness | ||||
| 	float32 k2; | ||||
| 	 | ||||
| 	// Damping | ||||
| 	float32 kd; | ||||
| 	float32 kb; | ||||
|  | ||||
| 	// Cloth thickness | ||||
| 	float32 r; | ||||
| 	// Damping stiffness | ||||
| 	float32 kd; | ||||
| }; | ||||
|  | ||||
| // Static particles have zero mass and velocity, and therefore they can't move. | ||||
| // Kinematic particles are't moved by external and internal forces but can be moved by contact forces. | ||||
| // Dynamic particles have non-zero mass and can move due to internal and external forces. | ||||
| enum b3ParticleType | ||||
| { | ||||
| 	e_staticParticle, | ||||
| 	e_kinematicParticle, | ||||
| 	e_dynamicParticle | ||||
| }; | ||||
|  | ||||
| // Read-only particle  | ||||
| struct b3Particle | ||||
| { | ||||
| 	float32 im; | ||||
| 	b3Vec3 p0; | ||||
| 	b3Vec3 p; | ||||
| 	b3Vec3 v; | ||||
| 	// Particle type | ||||
| 	b3ParticleType type; | ||||
|  | ||||
| 	// Mass position | ||||
| 	b3Vec3 position; | ||||
|  | ||||
| 	// Mass velocity | ||||
| 	b3Vec3 velocity; | ||||
| 	 | ||||
| 	// Mass force | ||||
| 	b3Vec3 force; | ||||
| 	 | ||||
| 	// Mass tension force for visualization | ||||
| 	b3Vec3 tension; | ||||
|  | ||||
| 	// Mass | ||||
| 	float32 mass; | ||||
| 	 | ||||
| 	// Inverse mass | ||||
| 	float32 invMass; | ||||
| 	 | ||||
| 	// Radius | ||||
| 	float32 radius; | ||||
|  | ||||
| 	// User data | ||||
| 	void* userData; | ||||
|  | ||||
| 	// Translation used for direct position manipulation | ||||
| 	b3Vec3 translation; | ||||
|  | ||||
| 	// Solver temp | ||||
|  | ||||
| 	// Identifier | ||||
| 	u32 solverId; | ||||
| 	 | ||||
| 	// Solution | ||||
| 	b3Vec3 x; | ||||
| }; | ||||
|  | ||||
| struct b3C1 | ||||
| // Spring types | ||||
| enum b3SpringType | ||||
| { | ||||
| 	float32 L; | ||||
| 	u32 i1; | ||||
| 	u32 i2; | ||||
| 	e_strechSpring, | ||||
| 	e_bendSpring, | ||||
| }; | ||||
|  | ||||
| struct b3C2 | ||||
| // Read-only spring | ||||
| struct b3Spring | ||||
| { | ||||
| 	float32 angle; | ||||
| 	u32 i1; | ||||
| 	u32 i2; | ||||
| 	u32 i3; | ||||
| 	u32 i4; | ||||
| 	// Spring type | ||||
| 	b3SpringType type; | ||||
|  | ||||
| 	// Particle 1 | ||||
| 	b3Particle* p1; | ||||
|  | ||||
| 	// Particle 2 | ||||
| 	b3Particle* p2; | ||||
|  | ||||
| 	// Rest length | ||||
| 	float32 L0; | ||||
|  | ||||
| 	// Structural stiffness | ||||
| 	float32 ks; | ||||
| 	 | ||||
| 	// Damping stiffness | ||||
| 	float32 kd; | ||||
| }; | ||||
|  | ||||
| // Read-only contact | ||||
| struct b3ParticleContact | ||||
| { | ||||
| 	b3Particle* p1; | ||||
| 	b3Shape* s2; | ||||
| 	b3Vec3 n, t1, t2; | ||||
| 	float32 Fn, Ft1, Ft2; | ||||
| 	bool n_active, t1_active, t2_active; | ||||
| }; | ||||
|  | ||||
| // A cloth represents a deformable surface/mesh. | ||||
| // b3Cloth simulates this surface motion using particles and springs. | ||||
| class b3Cloth | ||||
| { | ||||
| public: | ||||
| 	b3Cloth(); | ||||
| 	~b3Cloth(); | ||||
|  | ||||
| 	// Initialize this cloth from a definition. | ||||
| 	void Initialize(const b3ClothDef& def); | ||||
|  | ||||
| 	void Step(float32 dt, u32 iterations); | ||||
| 	// Return the cloth mesh used to initialize this cloth. | ||||
| 	b3ClothMesh* GetMesh() const; | ||||
|  | ||||
| 	u32 GetVertexCount() const | ||||
| 	{ | ||||
| 		return m_pCount; | ||||
| 	} | ||||
| 	// Set the gravitational acceleration applied to this cloth. | ||||
| 	// Units are m/s^2. | ||||
| 	void SetGravity(const b3Vec3& gravity); | ||||
|  | ||||
| 	const b3Particle* GetVertices() const | ||||
| 	{ | ||||
| 		return m_ps; | ||||
| 	} | ||||
| 	// Return the gravitational acceleration applied to this cloth. | ||||
| 	const b3Vec3& GetGravity() const; | ||||
|  | ||||
| 	b3Particle* GetVertices() | ||||
| 	{ | ||||
| 		return m_ps; | ||||
| 	} | ||||
| 	// Return the number of particles in this cloth. | ||||
| 	u32 GetParticleCount() const; | ||||
|  | ||||
| 	// Return the particle at a given index in this cloth. | ||||
| 	b3Particle* GetParticle(u32 i) const; | ||||
| 	 | ||||
| 	// Set the type of a given particle. | ||||
| 	void SetType(b3Particle* p, b3ParticleType type); | ||||
|  | ||||
| 	// Translate a particle in the next time step. | ||||
| 	void Translate(b3Particle* p, const b3Vec3& translation); | ||||
|  | ||||
| 	// Set the velocity of a given particle. | ||||
| 	void SetVelocity(b3Particle* p, const b3Vec3& velocity); | ||||
|  | ||||
| 	// Apply a force to a given particle. | ||||
| 	void ApplyForce(b3Particle* p, const b3Vec3& force); | ||||
|  | ||||
| 	// 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); | ||||
|  | ||||
| 	// 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); | ||||
|  | ||||
| 	// 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; | ||||
| private: | ||||
| 	void SolveC1(); | ||||
| 	void SolveC2(); | ||||
| protected: | ||||
| 	// Compute mass of each particle. | ||||
| 	void ResetMass(); | ||||
|  | ||||
| 	b3Particle* m_ps; | ||||
| 	u32 m_pCount; | ||||
| 	 | ||||
| 	b3C1* m_c1s; | ||||
| 	u32 m_c1Count; | ||||
| 	 | ||||
| 	b3C2* m_c2s; | ||||
| 	u32 m_c2Count; | ||||
| 	// Update contacts.  | ||||
| 	// This is where some contacts might be initiated or terminated. | ||||
| 	void UpdateContacts(); | ||||
|  | ||||
| 	// Solve | ||||
| 	void Solve(float32 dt); | ||||
|  | ||||
| 	b3StackAllocator m_allocator; | ||||
|  | ||||
| 	float32 m_k1; | ||||
| 	float32 m_k2; | ||||
| 	float32 m_kd; | ||||
| 	float32 m_r; | ||||
| 	b3Vec3 m_gravity; | ||||
|  | ||||
| 	const b3Mesh* m_mesh; | ||||
| 	u32 m_particleCount; | ||||
| 	b3Particle* m_particles; | ||||
|  | ||||
| 	b3Spring* m_springs; | ||||
| 	u32 m_springCount; | ||||
|  | ||||
| 	b3ParticleContact* m_contacts; | ||||
| 	//u32 m_contactCount; | ||||
|  | ||||
| 	b3Shape* m_shapes[B3_CLOTH_SHAPE_CAPACITY]; | ||||
| 	u32 m_shapeCount; | ||||
|  | ||||
| 	b3ClothMesh* m_mesh; | ||||
| 	float32 m_density; | ||||
| }; | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| inline b3Particle* b3Cloth::GetParticle(u32 i) const | ||||
| { | ||||
| 	B3_ASSERT(i < m_particleCount); | ||||
| 	return m_particles + i; | ||||
| } | ||||
|  | ||||
| inline void b3Cloth::SetType(b3Particle* p, b3ParticleType type) | ||||
| { | ||||
| 	if (p->type == type) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	p->type = type; | ||||
| 	p->force.SetZero(); | ||||
| 	 | ||||
| 	if (type == e_staticParticle) | ||||
| 	{ | ||||
| 		p->velocity.SetZero(); | ||||
| 		p->translation.SetZero(); | ||||
|  | ||||
| 		u32 ip = u32(p - m_particles); | ||||
|  | ||||
| 		m_contacts[ip].n_active = false; | ||||
| 		m_contacts[ip].t1_active = false; | ||||
| 		m_contacts[ip].t2_active = false; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| inline void b3Cloth::Translate(b3Particle* p, const b3Vec3& translation) | ||||
| { | ||||
| 	p->translation += translation; | ||||
| } | ||||
|  | ||||
| inline void b3Cloth::SetVelocity(b3Particle* p, const b3Vec3& velocity) | ||||
| { | ||||
| 	if (p->type == e_staticParticle) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	p->velocity = velocity; | ||||
| } | ||||
|  | ||||
| inline void b3Cloth::ApplyForce(b3Particle* p, const b3Vec3& force) | ||||
| { | ||||
| 	if (p->type != e_dynamicParticle) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	p->force += force; | ||||
| } | ||||
|  | ||||
| inline float32 b3Cloth::GetEnergy() const | ||||
| { | ||||
| 	float32 E = 0.0f; | ||||
| 	for (u32 i = 0; i < m_particleCount; ++i) | ||||
| 	{ | ||||
| 		E += m_particles[i].mass * b3Dot(m_particles[i].velocity, m_particles[i].velocity); | ||||
| 	} | ||||
| 	return 0.5f * E; | ||||
| } | ||||
|  | ||||
| inline u32 b3Cloth::GetShapeCount() const | ||||
| { | ||||
| 	return m_shapeCount; | ||||
| } | ||||
|  | ||||
| inline b3Shape** b3Cloth::GetShapeList()  | ||||
| { | ||||
| 	return m_shapes; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -16,48 +16,48 @@ | ||||
| * 3. This notice may not be removed or altered from any source distribution. | ||||
| */ | ||||
| 
 | ||||
| #ifndef B3_SPRING_SOLVER_H | ||||
| #define B3_SPRING_SOLVER_H | ||||
| #ifndef B3_CLOTH_SOLVER_H | ||||
| #define B3_CLOTH_SOLVER_H | ||||
| 
 | ||||
| #include <bounce/common/math/vec3.h> | ||||
| #include <bounce/common/math/mat33.h> | ||||
| 
 | ||||
| class b3Shape; | ||||
| 
 | ||||
| class b3SpringCloth; | ||||
| class b3StackAllocator; | ||||
| 
 | ||||
| struct b3DenseVec3; | ||||
| struct b3DiagMat33; | ||||
| struct b3SparseMat33; | ||||
| 
 | ||||
| struct b3MassContact; | ||||
| struct b3Particle; | ||||
| struct b3Spring; | ||||
| struct b3ParticleContact; | ||||
| 
 | ||||
| enum class b3MassType : u32; | ||||
| class b3Shape; | ||||
| class b3StackAllocator; | ||||
| 
 | ||||
| struct b3SpringSolverDef | ||||
| struct b3ClothSolverDef | ||||
| { | ||||
| 	b3SpringCloth* cloth; | ||||
| 	float32 dt; | ||||
| 	b3StackAllocator* stack; | ||||
| 	u32 particleCapacity; | ||||
| 	u32 springCapacity; | ||||
| 	u32 contactCapacity; | ||||
| }; | ||||
| 
 | ||||
| class b3SpringSolver | ||||
| class b3ClothSolver | ||||
| { | ||||
| public: | ||||
| 	b3SpringSolver(const b3SpringSolverDef& def); | ||||
| 	b3ClothSolver(const b3ClothSolverDef& def); | ||||
| 	~b3ClothSolver(); | ||||
| 	 | ||||
| 	void Add(b3Particle* p); | ||||
| 	void Add(b3Spring* s); | ||||
| 	void Add(b3ParticleContact* c); | ||||
| 
 | ||||
| 	~b3SpringSolver(); | ||||
| 
 | ||||
| 	void Solve(b3DenseVec3& extraForces); | ||||
| 
 | ||||
| 	u32 GetIterations() const; | ||||
| 	void Solve(float32 dt, const b3Vec3& gravity); | ||||
| private: | ||||
| 	// Apply internal forces and store their unique derivatives.
 | ||||
| 	void ApplySpringForces(); | ||||
| 
 | ||||
| 	// Compute forces.
 | ||||
| 	void Compute_f(b3DenseVec3& f, const b3DenseVec3& x, const b3DenseVec3& v, const b3Vec3& gravity); | ||||
| 	 | ||||
| 	// Compute A and b in Ax = b
 | ||||
| 	void Compute_A_b(b3SparseMat33& A, b3DenseVec3& b) const; | ||||
| 	void Compute_A_b(b3SparseMat33& A, b3DenseVec3& b, const b3DenseVec3& f, const b3DenseVec3& x, const b3DenseVec3& v, const b3DenseVec3& y) const; | ||||
| 
 | ||||
| 	// Compute S.
 | ||||
| 	void Compute_S(b3DiagMat33& S); | ||||
| @@ -67,38 +67,25 @@ private: | ||||
| 
 | ||||
| 	// Solve Ax = b.
 | ||||
| 	// Output x and the residual error f = Ax - b ~ 0.
 | ||||
| 	void Solve(b3DenseVec3& x, b3DenseVec3& f, u32& iterations, const b3SparseMat33& A, const b3DenseVec3& b, const b3DiagMat33& S, const b3DenseVec3& z, const b3DenseVec3& y) const; | ||||
| 
 | ||||
| 	b3SpringCloth * m_cloth; | ||||
| 	float32 m_h; | ||||
| 	b3Mat33* m_Jx; | ||||
| 	b3Mat33* m_Jv; | ||||
| 	u32 m_iterations; | ||||
| 	void Solve(b3DenseVec3& x, u32& iterations, const b3SparseMat33& A, const b3DenseVec3& b, const b3DiagMat33& S, const b3DenseVec3& z, const b3DenseVec3& y) const; | ||||
| 
 | ||||
| 	b3StackAllocator* m_allocator; | ||||
| 
 | ||||
| 	b3Vec3* m_x; | ||||
| 	b3Vec3* m_v; | ||||
| 	b3Vec3* m_f; | ||||
| 	float32* m_m; | ||||
| 	float32* m_inv_m; | ||||
| 	b3Vec3* m_y; | ||||
| 	b3Vec3* m_z; | ||||
| 	b3Vec3* m_x0; | ||||
| 	b3MassType* m_types; | ||||
| 	u32 m_massCount; | ||||
| 	float32 m_h; | ||||
| 	 | ||||
| 	u32 m_particleCapacity; | ||||
| 	u32 m_particleCount; | ||||
| 	b3Particle** m_particles; | ||||
| 
 | ||||
| 	b3MassContact* m_contacts; | ||||
| 	 | ||||
| 	b3Spring* m_springs; | ||||
| 	u32 m_springCapacity; | ||||
| 	u32 m_springCount; | ||||
| 	 | ||||
| 	b3Shape** m_shapes; | ||||
| 	b3Spring** m_springs; | ||||
| 	b3Mat33* m_Jx; | ||||
| 	b3Mat33* m_Jv; | ||||
| 
 | ||||
| 	u32 m_contactCapacity; | ||||
| 	u32 m_contactCount; | ||||
| 	b3ParticleContact** m_contacts; | ||||
| }; | ||||
| 
 | ||||
| inline u32 b3SpringSolver::GetIterations() const | ||||
| { | ||||
| 	return m_iterations; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| @@ -1,356 +0,0 @@ | ||||
| /* | ||||
| * Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net | ||||
| * | ||||
| * 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_SPRING_CLOTH_H | ||||
| #define B3_SPRING_CLOTH_H | ||||
|  | ||||
| #include <bounce/common/math/mat33.h> | ||||
| #include <bounce/common/template/array.h> | ||||
|  | ||||
| // Maximum number of shapes per cloth. | ||||
| #define B3_CLOTH_SHAPE_CAPACITY 32 | ||||
|  | ||||
| class b3StackAllocator; | ||||
|  | ||||
| class b3Shape; | ||||
|  | ||||
| struct b3ClothMesh; | ||||
|  | ||||
| struct b3SpringClothDef | ||||
| { | ||||
| 	b3SpringClothDef() | ||||
| 	{ | ||||
| 		allocator = nullptr; | ||||
| 		mesh = nullptr; | ||||
| 		density = 0.0f; | ||||
| 		ks = 0.0f; | ||||
| 		kb = 0.0f; | ||||
| 		kd = 0.0f; | ||||
| 		r = 0.05f; | ||||
| 		gravity.SetZero(); | ||||
| 	} | ||||
|  | ||||
| 	// Stack allocator | ||||
| 	b3StackAllocator* allocator; | ||||
|  | ||||
| 	// Cloth mesh	 | ||||
| 	b3ClothMesh* mesh; | ||||
|  | ||||
| 	// Cloth density in kg/m^3 | ||||
| 	float32 density; | ||||
|  | ||||
| 	// Streching stiffness | ||||
| 	float32 ks; | ||||
|  | ||||
| 	// Bending stiffness | ||||
| 	float32 kb; | ||||
|  | ||||
| 	// Damping stiffness | ||||
| 	float32 kd; | ||||
| 	 | ||||
| 	// Mass radius | ||||
| 	// This should be a small value. It can be used for correcting visual artifacts when  | ||||
| 	// the masses are colliding against a solid. | ||||
| 	float32 r; | ||||
| 	 | ||||
| 	// Acceleration due to gravity (m/s^2) | ||||
| 	b3Vec3 gravity; | ||||
| }; | ||||
|  | ||||
| enum b3SpringType | ||||
| { | ||||
| 	e_strechSpring, | ||||
| 	e_bendSpring, | ||||
| 	// e_sewingSpring | ||||
| }; | ||||
|  | ||||
| struct b3Spring | ||||
| { | ||||
| 	// Spring type | ||||
| 	b3SpringType type; | ||||
|  | ||||
| 	// Mass 1 | ||||
| 	u32 i1; | ||||
|  | ||||
| 	// Mass 2 | ||||
| 	u32 i2; | ||||
|  | ||||
| 	// Rest length | ||||
| 	float32 L0; | ||||
|  | ||||
| 	// Structural stiffness | ||||
| 	float32 ks; | ||||
| 	 | ||||
| 	// Damping stiffness | ||||
| 	float32 kd; | ||||
| }; | ||||
|  | ||||
| // Static masses have zero mass and velocity, and therefore they can't move. | ||||
| // Kinematic masses are't moved by external and internal forces but can be moved by contact forces. | ||||
| // Dynamic masses have non-zero mass and can move due to internal and external forces. | ||||
| enum class b3MassType : u32 | ||||
| { | ||||
| 	e_staticMass, | ||||
| 	e_kinematicMass, | ||||
| 	e_dynamicMass | ||||
| }; | ||||
|  | ||||
| //  | ||||
| struct b3MassContact | ||||
| { | ||||
| 	u32 j; | ||||
| 	b3Vec3 n, t1, t2; | ||||
| 	float32 Fn, Ft1, Ft2; | ||||
| 	bool lockN, lockT1, lockT2; | ||||
| }; | ||||
|  | ||||
| // Time step statistics | ||||
| struct b3SpringClothStep | ||||
| { | ||||
| 	u32 iterations; | ||||
| }; | ||||
|  | ||||
| // A cloth it treats cloth as a collection of masses connected by springs.  | ||||
| // Large time steps can be taken. | ||||
| // If accuracy and stability are required, not performance,  | ||||
| // you can use this class instead of using b3Cloth. | ||||
| class b3SpringCloth | ||||
| { | ||||
| public: | ||||
| 	b3SpringCloth(); | ||||
| 	~b3SpringCloth(); | ||||
|  | ||||
| 	// Initialize this cloth from a definition. | ||||
| 	void Initialize(const b3SpringClothDef& def); | ||||
|  | ||||
| 	// 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 number of masses in this cloth. | ||||
| 	u32 GetMassCount() const; | ||||
|  | ||||
| 	// Return the gravitational acceleration applied to this cloth. | ||||
| 	const b3Vec3& GetGravity() const; | ||||
|  | ||||
| 	// Set the type of a given point mass. | ||||
| 	void SetType(u32 i, b3MassType type); | ||||
|  | ||||
| 	// Return the type of a given point mass. | ||||
| 	b3MassType GetType(u32 i) const; | ||||
|  | ||||
| 	// Set the position of a given point mass. | ||||
| 	// This function will have effect on the position of the point mass  | ||||
| 	// after performing a time step. | ||||
| 	void SetPosition(u32 i, const b3Vec3& position); | ||||
|  | ||||
| 	// Return the position of a given point mass. | ||||
| 	const b3Vec3& GetPosition(u32 i) const; | ||||
|  | ||||
| 	// Set the velocity of a given point mass. | ||||
| 	void SetVelocity(u32 i, const b3Vec3& velocity); | ||||
|  | ||||
| 	// Return the velocity of a given point mass. | ||||
| 	const b3Vec3& GetVelocity(u32 i) const; | ||||
| 	 | ||||
| 	// Apply a force to a given point mass. | ||||
| 	void ApplyForce(u32 i, const b3Vec3& force); | ||||
|  | ||||
| 	// Return the kinetic (or dynamic) energy in this system. | ||||
| 	float32 GetEnergy() const; | ||||
| 	 | ||||
| 	// Return the tension forces (due to springs) acting at each point mass. | ||||
| 	// Units are kg * m / s^2 | ||||
| 	void GetTension(b3Array<b3Vec3>& tensions) const; | ||||
|  | ||||
| 	// Add a 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. | ||||
| 	void AddShape(b3Shape* shape); | ||||
|  | ||||
| 	// Return the number of shapes added to this cloth. | ||||
| 	u32 GetShapeCount() const; | ||||
|  | ||||
| 	// Return the list of shapes added to this cloth. | ||||
| 	b3Shape** GetShapes(); | ||||
|  | ||||
| 	// Return the statistics of the last time step. | ||||
| 	const b3SpringClothStep& GetStep() const; | ||||
|  | ||||
| 	// Perform a time step (marches time forward). | ||||
| 	void Step(float32 dt); | ||||
|  | ||||
| 	// Set the positions of the mesh vertices to the positions of their associated point masses. | ||||
| 	void Apply() const; | ||||
|  | ||||
| 	// Debug draw the cloth mesh. | ||||
| 	void Draw() const; | ||||
| protected: | ||||
| 	friend class b3SpringSolver; | ||||
| 	 | ||||
| 	// Update contacts.  | ||||
| 	// This is where some contacts might be initiated or terminated. | ||||
| 	void UpdateContacts(); | ||||
|  | ||||
| 	b3StackAllocator* m_allocator; | ||||
|  | ||||
| 	b3ClothMesh* m_mesh; | ||||
| 	float32 m_r; | ||||
|  | ||||
| 	b3Vec3 m_gravity; | ||||
|  | ||||
| 	b3Vec3* m_x; | ||||
| 	b3Vec3* m_v; | ||||
| 	b3Vec3* m_f; | ||||
| 	float32* m_m; | ||||
| 	float32* m_inv_m; | ||||
| 	b3Vec3* m_y; | ||||
| 	b3Vec3* m_z; | ||||
| 	b3Vec3* m_x0; | ||||
| 	b3MassType* m_types; | ||||
| 	u32 m_massCount; | ||||
|  | ||||
| 	b3MassContact* m_contacts; | ||||
| 	 | ||||
| 	b3Spring* m_springs; | ||||
| 	u32 m_springCount; | ||||
|  | ||||
| 	b3Shape* m_shapes[B3_CLOTH_SHAPE_CAPACITY]; | ||||
| 	u32 m_shapeCount; | ||||
|  | ||||
| 	b3SpringClothStep m_step; | ||||
| }; | ||||
|  | ||||
| inline b3ClothMesh* b3SpringCloth::GetMesh() const | ||||
| { | ||||
| 	return m_mesh; | ||||
| } | ||||
|  | ||||
| inline const b3Vec3& b3SpringCloth::GetGravity() const | ||||
| { | ||||
| 	return m_gravity; | ||||
| } | ||||
|  | ||||
| inline void b3SpringCloth::SetGravity(const b3Vec3& gravity) | ||||
| { | ||||
| 	m_gravity = gravity; | ||||
| } | ||||
|  | ||||
| inline u32 b3SpringCloth::GetMassCount() const | ||||
| { | ||||
| 	return m_massCount; | ||||
| } | ||||
|  | ||||
| inline b3MassType b3SpringCloth::GetType(u32 i) const | ||||
| { | ||||
| 	B3_ASSERT(i < m_massCount); | ||||
| 	return m_types[i]; | ||||
| } | ||||
|  | ||||
| inline void b3SpringCloth::SetType(u32 i, b3MassType type) | ||||
| { | ||||
| 	B3_ASSERT(i < m_massCount); | ||||
| 	 | ||||
| 	if (m_types[i] == type) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	m_types[i] = type; | ||||
| 	 | ||||
| 	m_f[i].SetZero(); | ||||
| 	 | ||||
| 	if (type == b3MassType::e_staticMass) | ||||
| 	{ | ||||
| 		m_v[i].SetZero(); | ||||
| 		m_y[i].SetZero(); | ||||
| 		 | ||||
| 		m_contacts[i].lockN = false; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| inline void b3SpringCloth::SetPosition(u32 i, const b3Vec3& position) | ||||
| { | ||||
| 	B3_ASSERT(i < m_massCount); | ||||
| 	m_y[i] += position - m_x[i]; | ||||
| } | ||||
|  | ||||
| inline const b3Vec3& b3SpringCloth::GetPosition(u32 i) const | ||||
| { | ||||
| 	B3_ASSERT(i < m_massCount); | ||||
| 	return m_x[i]; | ||||
| } | ||||
|  | ||||
| inline void b3SpringCloth::SetVelocity(u32 i, const b3Vec3& velocity) | ||||
| { | ||||
| 	B3_ASSERT(i < m_massCount); | ||||
| 	 | ||||
| 	if (m_types[i] == b3MassType::e_staticMass) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	m_v[i] = velocity; | ||||
| } | ||||
|  | ||||
| inline const b3Vec3& b3SpringCloth::GetVelocity(u32 i) const | ||||
| { | ||||
| 	B3_ASSERT(i < m_massCount); | ||||
| 	return m_v[i]; | ||||
| } | ||||
|  | ||||
| inline void b3SpringCloth::ApplyForce(u32 i, const b3Vec3& force) | ||||
| { | ||||
| 	B3_ASSERT(i < m_massCount); | ||||
| 	 | ||||
| 	if (m_types[i] != b3MassType::e_dynamicMass) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	m_f[i] += force; | ||||
| } | ||||
|  | ||||
| inline float32 b3SpringCloth::GetEnergy() const | ||||
| { | ||||
| 	float32 E = 0.0f; | ||||
| 	for (u32 i = 0; i < m_massCount; ++i) | ||||
| 	{ | ||||
| 		E += m_m[i] * b3Dot(m_v[i], m_v[i]); | ||||
| 	} | ||||
| 	return 0.5f * E; | ||||
| } | ||||
|  | ||||
| inline u32 b3SpringCloth::GetShapeCount() const | ||||
| { | ||||
| 	return m_shapeCount; | ||||
| } | ||||
|  | ||||
| inline b3Shape** b3SpringCloth::GetShapes()  | ||||
| { | ||||
| 	return m_shapes; | ||||
| } | ||||
|  | ||||
| inline const b3SpringClothStep& b3SpringCloth::GetStep() const | ||||
| { | ||||
| 	return m_step; | ||||
| } | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user