MassSpringArbitrary.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. #include <set>
  10. namespace WwiseGTE
  11. {
  12. template <int N, typename Real>
  13. class MassSpringArbitrary : public ParticleSystem<N, Real>
  14. {
  15. public:
  16. // Construction and destruction. This class represents a set of M
  17. // masses that are connected by S springs with arbitrary topology.
  18. // The function SetSpring(...) should be called for each spring that
  19. // you want in the system.
  20. virtual ~MassSpringArbitrary() = default;
  21. MassSpringArbitrary(int numParticles, int numSprings, Real step)
  22. :
  23. ParticleSystem<N, Real>(numParticles, step),
  24. mSpring(numSprings, Spring()),
  25. mAdjacent(numParticles)
  26. {
  27. }
  28. struct Spring
  29. {
  30. Spring()
  31. :
  32. particle0(0),
  33. particle1(0),
  34. constant((Real)0),
  35. length((Real)0)
  36. {
  37. }
  38. int particle0, particle1;
  39. Real constant, length;
  40. };
  41. // Member access.
  42. inline int GetNumSprings() const
  43. {
  44. return static_cast<int>(mSpring.size());
  45. }
  46. void SetSpring(int index, Spring const& spring)
  47. {
  48. mSpring[index] = spring;
  49. mAdjacent[spring.particle0].insert(index);
  50. mAdjacent[spring.particle1].insert(index);
  51. }
  52. inline Spring const& GetSpring(int index) const
  53. {
  54. return mSpring[index];
  55. }
  56. // The default external force is zero. Derive a class from this one
  57. // to provide nonzero external forces such as gravity, wind, friction,
  58. // and so on. This function is called by Acceleration(...) to compute
  59. // the impulse F/m generated by the external force F.
  60. virtual Vector<N, Real> ExternalAcceleration(int, Real,
  61. std::vector<Vector<N, Real>> const&,
  62. std::vector<Vector<N, Real>> const&)
  63. {
  64. return Vector<N, Real>::Zero();
  65. }
  66. protected:
  67. // Callback for acceleration (ODE solver uses x" = F/m) applied to
  68. // particle i. The positions and velocities are not necessarily
  69. // mPosition and mVelocity, because the ODE solver evaluates the
  70. // impulse function at intermediate positions.
  71. virtual Vector<N, Real> Acceleration(int i, Real time,
  72. std::vector<Vector<N, Real>> const& position,
  73. std::vector<Vector<N, Real>> const& velocity)
  74. {
  75. // Compute spring forces on position X[i]. The positions are not
  76. // necessarily mPosition, because the RK4 solver in ParticleSystem
  77. // evaluates the acceleration function at intermediate positions.
  78. Vector<N, Real> acceleration = ExternalAcceleration(i, time, position, velocity);
  79. for (auto adj : mAdjacent[i])
  80. {
  81. // Process a spring connected to particle i.
  82. Spring const& spring = mSpring[adj];
  83. Vector<N, Real> diff;
  84. if (i != spring.particle0)
  85. {
  86. diff = position[spring.particle0] - position[i];
  87. }
  88. else
  89. {
  90. diff = position[spring.particle1] - position[i];
  91. }
  92. Real ratio = spring.length / Length(diff);
  93. Vector<N, Real> force = spring.constant * ((Real)1 - ratio) * diff;
  94. acceleration += this->mInvMass[i] * force;
  95. }
  96. return acceleration;
  97. }
  98. std::vector<Spring> mSpring;
  99. // Each particle has an associated array of spring indices for those
  100. // springs adjacent to the particle. The set elements are spring
  101. // indices, not indices of adjacent particles.
  102. std::vector<std::set<int>> mAdjacent;
  103. };
  104. }