00001 #include "debug.h"
00002 #include "flock.h"
00003 #include "boid.h"
00004 #include "flockanimatortornado.h"
00005
00006 using namespace irr;
00007 using namespace core;
00008 using namespace scene;
00009
00010 extern Debug* dbg;
00011
00012 FlockAnimatorTornado::FlockAnimatorTornado(IrrlichtDevice* d)
00013 {
00014
00015 device = d;
00016 pi = 3.1415926535897932384626433832795f;
00017 oneOverTwoPi = 1.0f / (2.0f * pi);
00018 fluidDensity = 1.225f;
00019 gravitationalAccel = -9.8f;
00020 strength_0 = 0.5f;
00021 strength_500 = 250.0f;
00022 stormCenter = vector3df(0.0f, 0.0f, 0.0f);
00023 mass = 0.01f;
00024 halfRhoSref = pi * 3 * 3 * 0.5f * fluidDensity;
00025
00026 dbg->log("create FlockAnimatorTornado");
00027 }
00028
00029 FlockAnimatorTornado::~FlockAnimatorTornado()
00030 {
00031
00032 dbg->log("FlockAnimatorTornado deleted");
00033 }
00034
00035 void FlockAnimatorTornado::animateNode(ISceneNode* node, u32 timeMs)
00036 {
00037
00038 Flock* f = ((Flock*) node);
00039 stormCenter = f->getTarget();
00040 list<Boid*>::Iterator it = f->getBoidList().begin();
00041 for (; it != f->getBoidList().end(); ++it)
00042 {
00043 vector3df force = getForce((*it), timeMs);
00044 force *= f->getTornadoWeight();
00045 (*it)->velocity += force;
00046
00047
00048 if (it == f->getBoidList().begin())
00049 {
00050 dbg->show("first boid pos", (*it)->position);
00051 dbg->show("first boid force", force);
00052 }
00053 }
00054
00056 }
00057
00058
00059 f32 FlockAnimatorTornado::getWindStrength(f32 altitude)
00060 {
00061 return (strength_0 + ((strength_500 - strength_0) * altitude * altitude / 250000.0f));
00062 }
00063
00064
00066 vector3df FlockAnimatorTornado::getWindVelocity(vector3df location, u32 timeMs)
00067 {
00068
00069 vector3df result;
00070
00071 f32 dX = location.X - stormCenter.X;
00072 f32 dZ = location.Z - stormCenter.Z;
00073
00074 f32 r = sqrtf(dX * dX + dZ * dZ);
00075 if (r < 1.e-4)
00076 {
00077 r = 1.0f;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087 f32 oneOverR = 1.0f / r;
00088 if (oneOverR > 1.0f)
00089 {
00090 oneOverR = 1.0f;
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 #define TRUE_WIND_VELOCITY
00104 #ifdef TRUE_WIND_VELOCITY
00105 f32 commonFactor = getWindStrength(location.Z) * oneOverR * oneOverTwoPi;
00106
00107 result.X = dZ * commonFactor;
00108 result.Z = -dX * commonFactor;
00109 vector3df dbgCheck=result;
00110
00111 #else
00112 f32 physicsTimeStep = timeMs / 1000.f;
00113 f32 tangentialVelocity = getWindStrength(location.Y) * oneOverR * oneOverTwoPi;
00114 f32 deltaAngle = tangentialVelocity * physicsTimeStep;
00115 f32 angle = atan2(dZ, dX) + deltaAngle;
00116 f32 newX = r * cos(angle);
00117 f32 newZ = r * sin(angle);
00118 result.X = (newX - location.X) / physicsTimeStep;
00119 result.Z = (newZ - location.Z) / physicsTimeStep;
00120 #endif // TRUE_WIND_VELOCITY
00121
00122
00123
00124 result.Y = 0.0f;
00125
00126 return result;
00127 }
00128
00129 vector3df FlockAnimatorTornado::getForce(Boid* b, u32 timeMs)
00130 {
00131 vector3df result;
00132 vector3df wind;
00133 vector3df force;
00134 f32 dragMagnitude;
00135 f32 relwind_squared;
00136 f32 speed;
00137
00138 wind = getWindVelocity(b->position, timeMs);
00139
00140
00141 wind -= b->velocity;
00142
00143 relwind_squared = wind.X * wind.X + wind.Y * wind.Y + wind.Z * wind.Z;
00144 speed = sqrtf(relwind_squared);
00145
00146
00147
00148
00149 const float cd = 0.4f;
00150
00151 dragMagnitude = halfRhoSref * relwind_squared * cd;
00152
00153
00154 force = wind * dragMagnitude / speed;
00155
00156
00157 force.Y += gravitationalAccel * mass;
00158
00159
00160
00161
00162
00163 result = force / mass;
00164
00165 return result;
00166 }
00167