From 66228785fc24d0d7a9492be7a48e42686b826391 Mon Sep 17 00:00:00 2001 From: Irlan <-> Date: Fri, 18 May 2018 19:26:49 -0300 Subject: [PATCH] kinematic cloth --- include/bounce/dynamics/cloth/spring_cloth.h | 40 ++++++++++- src/bounce/dynamics/cloth/spring_cloth.cpp | 21 +++++- src/bounce/dynamics/cloth/spring_solver.cpp | 73 +++++++++----------- 3 files changed, 90 insertions(+), 44 deletions(-) diff --git a/include/bounce/dynamics/cloth/spring_cloth.h b/include/bounce/dynamics/cloth/spring_cloth.h index 9d9eb0c..bdbfad3 100644 --- a/include/bounce/dynamics/cloth/spring_cloth.h +++ b/include/bounce/dynamics/cloth/spring_cloth.h @@ -22,6 +22,7 @@ #include #include +// Number of maximum shapes per cloth. #define B3_CLOTH_SHAPE_CAPACITY 32 class b3StackAllocator; @@ -63,6 +64,8 @@ struct b3SpringClothDef float32 kd; // Mass radius + // Typically this is value is small and is intended for correcting visual artifacts when + // the cloth is colliding against a solid. float32 r; // Acceleration due to gravity (m/s^2) @@ -97,10 +100,12 @@ struct b3Spring }; // 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 }; @@ -140,6 +145,9 @@ public: // 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; @@ -152,11 +160,17 @@ public: // 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& translation); + 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); @@ -237,6 +251,11 @@ 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); @@ -246,6 +265,7 @@ inline b3MassType b3SpringCloth::GetType(u32 i) const inline void b3SpringCloth::SetType(u32 i, b3MassType type) { B3_ASSERT(i < m_massCount); + if (m_types[i] == type) { return; @@ -276,6 +296,24 @@ inline const b3Vec3& b3SpringCloth::GetPosition(u32 i) const 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); diff --git a/src/bounce/dynamics/cloth/spring_cloth.cpp b/src/bounce/dynamics/cloth/spring_cloth.cpp index abdaa46..e268fa8 100644 --- a/src/bounce/dynamics/cloth/spring_cloth.cpp +++ b/src/bounce/dynamics/cloth/spring_cloth.cpp @@ -400,7 +400,7 @@ void b3SpringCloth::GetTension(b3Array& T) const for (u32 i = 0; i < T.Count(); ++i) { - if (m_types[i] == b3MassType::e_staticMass) + if (m_types[i] != b3MassType::e_dynamicMass) { T[i].SetZero(); } @@ -677,11 +677,26 @@ void b3SpringCloth::Draw() const for (u32 i = 0; i < m->vertexCount; ++i) { - b3MassContact* c = m_contacts + i; + if (m_types[i] == b3MassType::e_staticMass) + { + b3Draw_draw->DrawPoint(m_x[i], 4.0f, b3Color_white); + } + + if (m_types[i] == b3MassType::e_kinematicMass) + { + b3Draw_draw->DrawPoint(m_x[i], 4.0f, b3Color_blue); + } + + if (m_types[i] == b3MassType::e_dynamicMass) + { + b3Draw_draw->DrawPoint(m_x[i], 4.0f, b3Color_green); + } + b3MassContact* c = m_contacts + i; + if (c->lockN) { - b3Draw_draw->DrawPoint(m_x[i], 6.0f, b3Color_green); + b3Draw_draw->DrawPoint(m_x[i], 6.0f, b3Color_yellow); b3Draw_draw->DrawSegment(m_x[i], m_x[i] + c->n, b3Color_yellow); diff --git a/src/bounce/dynamics/cloth/spring_solver.cpp b/src/bounce/dynamics/cloth/spring_solver.cpp index d803f99..0ab2eae 100644 --- a/src/bounce/dynamics/cloth/spring_solver.cpp +++ b/src/bounce/dynamics/cloth/spring_solver.cpp @@ -104,7 +104,10 @@ void b3SpringSolver::Solve(b3DenseVec3& f) // Update state for (u32 i = 0; i < m_massCount; ++i) { - m_v[i] += x[i]; + if (m_types[i] == b3MassType::e_dynamicMass) + { + m_v[i] += x[i]; + } // dx = h * (v0 + dv) + y = h * v1 + y m_x[i] += m_h * m_v[i] + m_y[i]; @@ -365,54 +368,44 @@ void b3SpringSolver::Compute_S(b3Mat33* out) { for (u32 i = 0; i < m_massCount; ++i) { - switch (m_types[i]) - { - case b3MassType::e_staticMass: + out[i].SetIdentity(); + + if (m_types[i] == b3MassType::e_staticMass) { out[i].SetZero(); - break; + continue; } - case b3MassType::e_dynamicMass: + + b3MassContact* c = m_contacts + i; + + if (c->lockN == true) { - if (m_contacts[i].lockN == true) + b3Vec3 n = c->n; + + b3Mat33 S = b3Mat33_identity - b3Outer(n, n); + + if (c->lockT1 == true && c->lockT2 == true) { - b3Vec3 n = m_contacts[i].n; - - b3Mat33 S = b3Mat33_identity - b3Outer(n, n); - - if (m_contacts[i].lockT1 == true && m_contacts[i].lockT2 == true) + S.SetZero(); + } + else + { + if (c->lockT1 == true) { - S.SetZero(); - } - else - { - if (m_contacts[i].lockT1 == true) - { - b3Vec3 t1 = m_contacts[i].t1; + b3Vec3 t1 = c->t1; - S -= b3Outer(t1, t1); - } - - if (m_contacts[i].lockT2 == true) - { - b3Vec3 t2 = m_contacts[i].t2; - - S -= b3Outer(t2, t2); - } + S -= b3Outer(t1, t1); } - out[i] = S; - break; + if (c->lockT2 == true) + { + b3Vec3 t2 = c->t2; + + S -= b3Outer(t2, t2); + } } - out[i].SetIdentity(); - break; - } - default: - { - B3_ASSERT(false); - break; - } + out[i] = S; } } } @@ -461,7 +454,7 @@ void b3SpringSolver::Solve(b3DenseVec3& dv, b3DenseVec3& e, u32& iterations, con // delta0 = dot(filter(b), P * filter(b)) b3DenseVec3 S_b(m_massCount); b3Filter(S_b, b, S, m_massCount); - + // P * filter(b) b3DenseVec3 P_S_b(m_massCount); for (u32 i = 0; i < m_massCount; ++i) @@ -529,7 +522,7 @@ void b3SpringSolver::Solve(b3DenseVec3& dv, b3DenseVec3& e, u32& iterations, con // deltaNew = dot(r, s) deltaNew = b3Dot(r, s); B3_ASSERT(b3IsValid(deltaNew)); - + // beta = deltaNew / deltaOld float32 beta = deltaNew / deltaOld;