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