forestWindAccumulator.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "forest/forestWindAccumulator.h"
  24. #include "forest/forestWindMgr.h"
  25. #include "forest/forestItem.h"
  26. #include "platform/profiler.h"
  27. ForestWindAccumulator::ForestWindAccumulator( const TreePlacementInfo &info )
  28. : mCurrentStrength( 0.0f )
  29. {
  30. mCurrentDir.set( 0, 0 );
  31. mPosition.set( info.pos );
  32. mScale = info.scale;
  33. mDataBlock = info.dataBlock;
  34. dMemset( &mParticles[0], 0, sizeof( VerletParticle ) );
  35. dMemset( &mParticles[1], 0, sizeof( VerletParticle ) );
  36. }
  37. ForestWindAccumulator::~ForestWindAccumulator()
  38. {
  39. }
  40. void ForestWindAccumulator::presimulate( const VectorF &windVector, U32 ticks )
  41. {
  42. PROFILE_SCOPE( ForestWindAccumulator_Presimulate );
  43. for ( U32 i = 0; i < ticks; i++ )
  44. updateWind( windVector, TickSec );
  45. }
  46. void ForestWindAccumulator::updateWind( const VectorF &windForce, F32 timeDelta )
  47. {
  48. PROFILE_SCOPE( ForestWindAccumulator_UpdateWind );
  49. // Update values from datablock... this way we can
  50. // change settings live and see instant results.
  51. const F32 tightnessCoefficient = mDataBlock->mTightnessCoefficient;
  52. const F32 dampingCoefficient = mDataBlock->mDampingCoefficient;
  53. const F32 mass = mDataBlock->mMass * mScale;
  54. const F32 rigidity = mDataBlock->mRigidity * mScale;
  55. // This will be the accumulated
  56. // target strength for flutter.
  57. //F32 targetStrength = windForce.len();
  58. // This will be the accumulated
  59. // target displacement vector.
  60. Point2F target( windForce.x, windForce.y );
  61. // This particle is the spring target.
  62. // It has a mass of 0, which we count as
  63. // an infinite mass.
  64. mParticles[0].position = target;
  65. Point2F diff( 0, 0 );
  66. Point2F springForce( 0, 0 );
  67. // Spring length is the target
  68. // particle's position minus the
  69. // current displacement/direction vector.
  70. diff = mParticles[0].position - mCurrentDir;
  71. // F = diff * tightness - v * -damping
  72. diff *= tightnessCoefficient;
  73. springForce = diff - ( (mParticles[1].position - mParticles[1].lastPosition) * -dampingCoefficient );
  74. Point2F accel( 0, 0 );
  75. accel = springForce * (rigidity * 0.001f) / (mass * 0.001f);
  76. _updateParticle( &mParticles[1], accel, timeDelta );
  77. mCurrentDir *= 0.989f;
  78. mCurrentDir += mParticles[1].position;
  79. mCurrentStrength += windForce.len() * timeDelta;
  80. mCurrentStrength *= 0.98f;
  81. }
  82. void ForestWindAccumulator::_updateParticle( VerletParticle *particle, const Point2F &accel, F32 timeDelta )
  83. {
  84. // Verlet integration:
  85. // x' = 2x - x* + a * dt^2
  86. // x' is the new position.
  87. // x is the current position.
  88. // x* is the last position.
  89. // a is the acceleration for this frame.
  90. // dt is the delta time.
  91. particle->position = ((particle->position * 2.0f) - particle->lastPosition) + accel * (timeDelta * timeDelta);
  92. particle->lastPosition = particle->position;
  93. }
  94. void ForestWindAccumulator::applyImpulse( const VectorF &impulse )
  95. {
  96. // First build the current force.
  97. VectorF force( mCurrentDir.x, mCurrentDir.y, 0 );
  98. // Add in our mass corrected force.
  99. const F32 mass = mDataBlock->mMass * mScale;
  100. force += impulse / mass;
  101. // Set the new direction and force.
  102. mCurrentDir.set( force.x, force.y );
  103. mCurrentStrength += impulse.len() * TickSec;
  104. }