This commit is contained in:
Irlan 2018-06-27 11:31:42 -03:00
parent 73777b9f1a
commit 2485f92ba4
5 changed files with 79 additions and 101 deletions

View File

@ -48,6 +48,8 @@ struct b3ClothSolverData
b3DenseVec3* y; b3DenseVec3* y;
b3SparseSymMat33* dfdx; b3SparseSymMat33* dfdx;
b3SparseSymMat33* dfdv; b3SparseSymMat33* dfdv;
b3DiagMat33* S;
b3DenseVec3* z;
float32 dt; float32 dt;
float32 invdt; float32 invdt;
}; };
@ -57,6 +59,8 @@ struct b3AccelerationConstraint
u32 i1; u32 i1;
u32 ndof; u32 ndof;
b3Vec3 p, q, z; b3Vec3 p, q, z;
void Apply(const b3ClothSolverData* data);
}; };
class b3ClothSolver class b3ClothSolver
@ -71,21 +75,15 @@ public:
void Solve(float32 dt, const b3Vec3& gravity); void Solve(float32 dt, const b3Vec3& gravity);
private: private:
// Initialize forces.
void InitializeForces();
// Apply forces. // Apply forces.
void ApplyForces(); void ApplyForces();
// Initialize constraints. // Apply constraints.
void InitializeConstraints(); void ApplyConstraints();
// Compute A and b in Ax = b // Compute A and b in Ax = b.
void Compute_A_b(b3SparseSymMat33& A, b3DenseVec3& b) const; void Compute_A_b(b3SparseSymMat33& A, b3DenseVec3& b) const;
// Compute S and z.
void Compute_S_z(b3DiagMat33& S, b3DenseVec3& z);
// Solve Ax = b. // Solve Ax = b.
void Solve(b3DenseVec3& x, u32& iterations, const b3SparseSymMat33& A, const b3DenseVec3& b, const b3DiagMat33& S, const b3DenseVec3& z, const b3DenseVec3& y) const; void Solve(b3DenseVec3& x, u32& iterations, const b3SparseSymMat33& A, const b3DenseVec3& b, const b3DiagMat33& S, const b3DenseVec3& z, const b3DenseVec3& y) const;

View File

@ -58,11 +58,8 @@ protected:
b3Force() { } b3Force() { }
virtual ~b3Force() { } virtual ~b3Force() { }
virtual void Initialize(const b3ClothSolverData* data) = 0;
virtual void Apply(const b3ClothSolverData* data) = 0; virtual void Apply(const b3ClothSolverData* data) = 0;
// Solver shared
// Force type // Force type
b3ForceType m_type; b3ForceType m_type;

View File

@ -73,9 +73,7 @@ private:
b3SpringForce(const b3SpringForceDef* def); b3SpringForce(const b3SpringForceDef* def);
~b3SpringForce(); ~b3SpringForce();
void Initialize(const b3ClothSolverData* data);
void Apply(const b3ClothSolverData* data); void Apply(const b3ClothSolverData* data);
// Solver shared // Solver shared
@ -95,16 +93,8 @@ private:
// Damping stiffness // Damping stiffness
float32 m_kd; float32 m_kd;
// Solver temp // Applied internal force (on particle 1)
// Force (f_1 entry)
b3Vec3 m_f; b3Vec3 m_f;
// Jacobian (J_11 entry)
b3Mat33 m_Jx;
// Jacobian (J_11 entry)
b3Mat33 m_Jv;
}; };
inline b3Particle * b3SpringForce::GetParticle1() inline b3Particle * b3SpringForce::GetParticle1()

View File

@ -79,14 +79,6 @@ void b3ClothSolver::Add(b3Force* f)
m_forces[m_forceCount++] = f; m_forces[m_forceCount++] = f;
} }
void b3ClothSolver::InitializeForces()
{
for (u32 i = 0; i < m_forceCount; ++i)
{
m_forces[i]->Initialize(&m_solverData);
}
}
void b3ClothSolver::ApplyForces() void b3ClothSolver::ApplyForces()
{ {
for (u32 i = 0; i < m_forceCount; ++i) for (u32 i = 0; i < m_forceCount; ++i)
@ -95,8 +87,50 @@ void b3ClothSolver::ApplyForces()
} }
} }
void b3ClothSolver::InitializeConstraints() void b3AccelerationConstraint::Apply(const b3ClothSolverData* data)
{ {
(*data->z)[i1] = z;
b3Mat33 I; I.SetIdentity();
switch (ndof)
{
case 3:
{
(*data->S)[i1] = I;
break;
}
case 2:
{
(*data->S)[i1] = I - b3Outer(p, p);
break;
}
case 1:
{
(*data->S)[i1] = I - b3Outer(p, p) - b3Outer(q, q);
break;
}
case 0:
{
(*data->S)[i1].SetZero();
break;
}
default:
{
B3_ASSERT(false);
break;
}
}
}
void b3ClothSolver::ApplyConstraints()
{
b3DiagMat33& S = *m_solverData.S;
b3DenseVec3& z = *m_solverData.z;
S.SetIdentity();
z.SetZero();
for (u32 i = 0; i < m_particleCount; ++i) for (u32 i = 0; i < m_particleCount; ++i)
{ {
b3Particle* p = m_particles[i]; b3Particle* p = m_particles[i];
@ -141,6 +175,11 @@ void b3ClothSolver::InitializeConstraints()
} }
} }
} }
for (u32 i = 0; i < m_constraintCount; ++i)
{
m_constraints[i].Apply(&m_solverData);
}
} }
void b3ClothSolver::Solve(float32 dt, const b3Vec3& gravity) void b3ClothSolver::Solve(float32 dt, const b3Vec3& gravity)
@ -152,6 +191,8 @@ void b3ClothSolver::Solve(float32 dt, const b3Vec3& gravity)
b3DenseVec3 sx0(m_particleCount); b3DenseVec3 sx0(m_particleCount);
b3SparseSymMat33 dfdx(m_particleCount); b3SparseSymMat33 dfdx(m_particleCount);
b3SparseSymMat33 dfdv(m_particleCount); b3SparseSymMat33 dfdv(m_particleCount);
b3DiagMat33 S(m_particleCount);
b3DenseVec3 z(m_particleCount);
m_solverData.x = &sx; m_solverData.x = &sx;
m_solverData.v = &sv; m_solverData.v = &sv;
@ -159,6 +200,8 @@ void b3ClothSolver::Solve(float32 dt, const b3Vec3& gravity)
m_solverData.y = &sy; m_solverData.y = &sy;
m_solverData.dfdx = &dfdx; m_solverData.dfdx = &dfdx;
m_solverData.dfdv = &dfdv; m_solverData.dfdv = &dfdv;
m_solverData.S = &S;
m_solverData.z = &z;
m_solverData.dt = dt; m_solverData.dt = dt;
m_solverData.invdt = 1.0f / dt; m_solverData.invdt = 1.0f / dt;
@ -188,19 +231,11 @@ void b3ClothSolver::Solve(float32 dt, const b3Vec3& gravity)
sy[p->m_solverId] -= c->s * c->n; sy[p->m_solverId] -= c->s * c->n;
} }
// Initialize internal forces
InitializeForces();
// Apply internal forces // Apply internal forces
ApplyForces(); ApplyForces();
// Initialize constraints // Apply constraints
InitializeConstraints(); ApplyConstraints();
// Compute S, z
b3DiagMat33 S(m_particleCount);
b3DenseVec3 z(m_particleCount);
Compute_S_z(S, z);
// Solve Ax = b, where // Solve Ax = b, where
// A = M - h * dfdv - h * h * dfdx // A = M - h * dfdv - h * h * dfdx
@ -267,7 +302,7 @@ void b3ClothSolver::Solve(float32 dt, const b3Vec3& gravity)
void b3ClothSolver::Compute_A_b(b3SparseSymMat33& A, b3DenseVec3& b) const void b3ClothSolver::Compute_A_b(b3SparseSymMat33& A, b3DenseVec3& b) const
{ {
B3_PROFILE("Compute A, b"); B3_PROFILE("Compute A, b");
b3DenseVec3& x = *m_solverData.x; b3DenseVec3& x = *m_solverData.x;
b3DenseVec3& v = *m_solverData.v; b3DenseVec3& v = *m_solverData.v;
b3DenseVec3& f = *m_solverData.f; b3DenseVec3& f = *m_solverData.f;
@ -289,7 +324,7 @@ void b3ClothSolver::Compute_A_b(b3SparseSymMat33& A, b3DenseVec3& b) const
} }
// A += - h * dfdv - h * h * dfdx // A += - h * dfdv - h * h * dfdx
// A += - h * dfdv // A += - h * dfdv
for (u32 row = 0; row < dfdv.M; ++row) for (u32 row = 0; row < dfdv.M; ++row)
{ {
@ -300,7 +335,7 @@ void b3ClothSolver::Compute_A_b(b3SparseSymMat33& A, b3DenseVec3& b) const
{ {
u32 row_value_index = row_value_begin + row_value; u32 row_value_index = row_value_begin + row_value;
u32 row_value_column = dfdv.value_columns[row_value_index]; u32 row_value_column = dfdv.value_columns[row_value_index];
A(row, row_value_column) += -h * dfdv.values[row_value_index]; A(row, row_value_column) += -h * dfdv.values[row_value_index];
} }
} }
@ -319,50 +354,13 @@ void b3ClothSolver::Compute_A_b(b3SparseSymMat33& A, b3DenseVec3& b) const
A(row, row_value_column) += -h * h * dfdx.values[row_value_index]; A(row, row_value_column) += -h * h * dfdx.values[row_value_index];
} }
} }
// Compute b // Compute b
// b = h * (f0 + h * dfdx * v + dfdx * y) // b = h * (f0 + h * dfdx * v + dfdx * y)
b = h * (f + h * (dfdx * v) + dfdx * y); b = h * (f + h * (dfdx * v) + dfdx * y);
} }
void b3ClothSolver::Compute_S_z(b3DiagMat33& S, b3DenseVec3& z)
{
S.SetIdentity();
z.SetZero();
for (u32 i = 0; i < m_constraintCount; ++i)
{
b3AccelerationConstraint* ac = m_constraints + i;
u32 ip = ac->i1;
u32 ndof = ac->ndof;
b3Vec3 p = ac->p;
b3Vec3 q = ac->q;
b3Vec3 cz = ac->z;
z[ip] = cz;
if (ndof == 2)
{
b3Mat33 I; I.SetIdentity();
S[ip] = I - b3Outer(p, p);
}
if (ndof == 1)
{
b3Mat33 I; I.SetIdentity();
S[ip] = I - b3Outer(p, p) - b3Outer(q, q);
}
if (ndof == 0)
{
S[ip].SetZero();
}
}
}
void b3ClothSolver::Solve(b3DenseVec3& x, u32& iterations, void b3ClothSolver::Solve(b3DenseVec3& x, u32& iterations,
const b3SparseSymMat33& A, const b3DenseVec3& b, const b3DiagMat33& S, const b3DenseVec3& z, const b3DenseVec3& y) const const b3SparseSymMat33& A, const b3DenseVec3& b, const b3DiagMat33& S, const b3DenseVec3& z, const b3DenseVec3& y) const
{ {
@ -415,7 +413,7 @@ void b3ClothSolver::Solve(b3DenseVec3& x, u32& iterations,
float32 delta_new = b3Dot(r, p); float32 delta_new = b3Dot(r, p);
// Set the tolerance. // Set the tolerance.
const float32 tolerance = 1.e-4f; const float32 tolerance = 10.0f * B3_EPSILON;
// Maximum number of iterations. // Maximum number of iterations.
// Stop at this iteration if diverged. // Stop at this iteration if diverged.

View File

@ -50,10 +50,13 @@ b3SpringForce::~b3SpringForce()
} }
void b3SpringForce::Initialize(const b3ClothSolverData* data) void b3SpringForce::Apply(const b3ClothSolverData* data)
{ {
b3DenseVec3& x = *data->x; b3DenseVec3& x = *data->x;
b3DenseVec3& v = *data->v; b3DenseVec3& v = *data->v;
b3DenseVec3& f = *data->f;
b3SparseSymMat33& dfdx = *data->dfdx;
b3SparseSymMat33& dfdv = *data->dfdv;
u32 i1 = m_p1->m_solverId; u32 i1 = m_p1->m_solverId;
u32 i2 = m_p2->m_solverId; u32 i2 = m_p2->m_solverId;
@ -70,6 +73,8 @@ void b3SpringForce::Initialize(const b3ClothSolverData* data)
float32 L = b3Length(dx); float32 L = b3Length(dx);
b3Mat33 Jx;
if (L >= m_L0) if (L >= m_L0)
{ {
b3Vec3 n = dx / L; b3Vec3 n = dx / L;
@ -78,34 +83,24 @@ void b3SpringForce::Initialize(const b3ClothSolverData* data)
m_f = -m_ks * (L - m_L0) * n; m_f = -m_ks * (L - m_L0) * n;
// Jacobian // Jacobian
m_Jx = -m_ks * (b3Outer(dx, dx) + (1.0f - m_L0 / L) * (I - b3Outer(dx, dx))); Jx = -m_ks * (b3Outer(dx, dx) + (1.0f - m_L0 / L) * (I - b3Outer(dx, dx)));
} }
else else
{ {
m_f.SetZero(); m_f.SetZero();
m_Jx.SetZero(); Jx.SetZero();
} }
// Damping // Damping
b3Vec3 dv = v1 - v2; b3Vec3 dv = v1 - v2;
m_f += -m_kd * dv; m_f += -m_kd * dv;
m_Jv = -m_kd * I; b3Mat33 Jv = -m_kd * I;
}
void b3SpringForce::Apply(const b3ClothSolverData* data)
{
b3DenseVec3& f = *data->f;
b3SparseSymMat33& dfdx = *data->dfdx;
b3SparseSymMat33& dfdv = *data->dfdv;
u32 i1 = m_p1->m_solverId;
u32 i2 = m_p2->m_solverId;
f[i1] += m_f; f[i1] += m_f;
f[i2] -= m_f; f[i2] -= m_f;
b3Mat33 Jx11 = m_Jx; b3Mat33 Jx11 = Jx;
b3Mat33 Jx12 = -Jx11; b3Mat33 Jx12 = -Jx11;
//b3Mat33 Jx21 = Jx12; //b3Mat33 Jx21 = Jx12;
b3Mat33 Jx22 = Jx11; b3Mat33 Jx22 = Jx11;
@ -115,7 +110,7 @@ void b3SpringForce::Apply(const b3ClothSolverData* data)
//dfdx(i2, i1) += Jx21; //dfdx(i2, i1) += Jx21;
dfdx(i2, i2) += Jx22; dfdx(i2, i2) += Jx22;
b3Mat33 Jv11 = m_Jv; b3Mat33 Jv11 = Jv;
b3Mat33 Jv12 = -Jv11; b3Mat33 Jv12 = -Jv11;
//b3Mat33 Jv21 = Jv12; //b3Mat33 Jv21 = Jv12;
b3Mat33 Jv22 = Jv11; b3Mat33 Jv22 = Jv11;