MassSpringCurve.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/ParticleSystem.h>
  9. namespace WwiseGTE
  10. {
  11. template <int N, typename Real>
  12. class MassSpringCurve : public ParticleSystem<N, Real>
  13. {
  14. public:
  15. // Construction and destruction. This class represents a set of N-1
  16. // springs connecting N masses that lie on a curve.
  17. virtual ~MassSpringCurve() = default;
  18. MassSpringCurve(int numParticles, Real step)
  19. :
  20. ParticleSystem<N, Real>(numParticles, step),
  21. mConstant(numParticles - 1),
  22. mLength(numParticles - 1)
  23. {
  24. std::fill(mConstant.begin(), mConstant.end(), (Real)0);
  25. std::fill(mLength.begin(), mLength.end(), (Real)0);
  26. }
  27. // Member access. The parameters are spring constant and spring
  28. // resting length.
  29. inline int GetNumSprings() const
  30. {
  31. return this->mNumParticles - 1;
  32. }
  33. inline void SetConstant(int i, Real constant)
  34. {
  35. mConstant[i] = constant;
  36. }
  37. inline void SetLength(int i, Real length)
  38. {
  39. mLength[i] = length;
  40. }
  41. inline Real const& GetConstant(int i) const
  42. {
  43. return mConstant[i];
  44. }
  45. inline Real const& GetLength(int i) const
  46. {
  47. return mLength[i];
  48. }
  49. // The default external force is zero. Derive a class from this one
  50. // to provide nonzero external forces such as gravity, wind, friction,
  51. // and so on. This function is called by Acceleration(...) to compute
  52. // the impulse F/m generated by the external force F.
  53. virtual Vector<N, Real> ExternalAcceleration(int, Real,
  54. std::vector<Vector<N, Real>> const&,
  55. std::vector<Vector<N, Real>> const&)
  56. {
  57. return Vector<N, Real>::Zero();
  58. }
  59. protected:
  60. // Callback for acceleration (ODE solver uses x" = F/m) applied to
  61. // particle i. The positions and velocities are not necessarily
  62. // mPosition and mVelocity, because the ODE solver evaluates the
  63. // impulse function at intermediate positions.
  64. virtual Vector<N, Real> Acceleration(int i, Real time,
  65. std::vector<Vector<N, Real>> const& position,
  66. std::vector<Vector<N, Real>> const& velocity)
  67. {
  68. // Compute spring forces on position X[i]. The positions are not
  69. // necessarily mPosition, because the RK4 solver in ParticleSystem
  70. // evaluates the acceleration function at intermediate positions.
  71. // The endpoints of the curve of masses must be handled
  72. // separately, because each has only one spring attached to it.
  73. Vector<N, Real> acceleration = ExternalAcceleration(i, time, position, velocity);
  74. Vector<N, Real> diff, force;
  75. Real ratio;
  76. if (i > 0)
  77. {
  78. int iM1 = i - 1;
  79. diff = position[iM1] - position[i];
  80. ratio = mLength[iM1] / Length(diff);
  81. force = mConstant[iM1] * ((Real)1 - ratio) * diff;
  82. acceleration += this->mInvMass[i] * force;
  83. }
  84. int iP1 = i + 1;
  85. if (iP1 < this->mNumParticles)
  86. {
  87. diff = position[iP1] - position[i];
  88. ratio = mLength[i] / Length(diff);
  89. force = mConstant[i] * ((Real)1 - ratio) * diff;
  90. acceleration += this->mInvMass[i] * force;
  91. }
  92. return acceleration;
  93. }
  94. std::vector<Real> mConstant, mLength;
  95. };
  96. }