00001 #include "debug.h"
00002 #include "flock.h"
00003 #include "boid.h"
00004 #include "flockanimatordefault.h"
00005
00006 using namespace irr;
00007 using namespace core;
00008 using namespace scene;
00009
00010 extern Debug* dbg;
00011
00012 FlockAnimatorDefault::FlockAnimatorDefault(IrrlichtDevice* d)
00013 {
00014
00015 device = d;
00016 dbg->log("create FlockAnimatorDefault");
00017 }
00018
00019 FlockAnimatorDefault::~FlockAnimatorDefault()
00020 {
00021
00022 dbg->log("FlockAnimatorDefault deleted");
00023 }
00024
00025 void FlockAnimatorDefault::testSpeedUp(ISceneNode* node)
00026 {
00027
00028
00029
00030 Flock* flock = ((Flock*) node);
00031 s32 maxDistance = flock->getNeighborRadius();
00032 vector3df seekTarget = flock->getTarget();
00033 s32 cosMaxAngle = 50;
00034 s32 neighbors = 0;
00035 vector3df steeringSeparation;
00036 s32 separationWeight = flock->getSeparationWeight();
00037 vector3df steeringAlignment;
00038 s32 alignmnetWeight = flock->getAlignmentWeight();
00039 vector3df steeringCohesion;
00040 s32 cohesionWeight = flock->getCohesionWeight();
00041 vector3df steeringSeekTarget;
00042 s32 seekTargetWeight = flock->getSeekTargetWeight();
00043
00044
00045 list<Boid*>::Iterator it = flock->getBoidList().begin();
00046 for (; it != flock->getBoidList().end(); ++it)
00047 {
00048 steeringSeparation.set(0.0f,0.0f,0.0f);
00049 steeringAlignment.set(0.0f,0.0f,0.0f);
00050 steeringCohesion.set(0.0f,0.0f,0.0f);
00051 steeringSeekTarget.set(0.0f,0.0f,0.0f);
00052 neighbors = 0;
00053
00054
00055 list<Boid*>::Iterator it2 = flock->getBoidList().begin();
00056 for (; it2 != flock->getBoidList().end(); ++it2)
00057 {
00058 if ((*it)->inBoidNeighborhood((*it2), maxDistance, maxDistance, cosMaxAngle))
00059 {
00060
00061 vector3df offset = (*it2)->position - (*it)->position;
00062 f32 distanceSquared = offset.dotProduct(offset);
00063 steeringSeparation += (offset / -distanceSquared);
00064
00065 steeringAlignment += (*it2)->forward;
00066
00067 steeringCohesion += (*it2)->position;
00068
00069 neighbors++;
00070 }
00071 }
00072
00073 if (neighbors > 0)
00074 {
00075
00076 steeringSeparation = (steeringSeparation / (f32) neighbors).normalize();
00077
00078 steeringAlignment = ((steeringAlignment / (f32) neighbors) - (*it)->forward).normalize();
00079
00080 steeringCohesion = ((steeringCohesion / (f32) neighbors) - (*it)->position).normalize();
00081 }
00082
00083
00084 vector3df desiredVelocity = seekTarget - (*it)->position;
00085 steeringSeekTarget = (desiredVelocity - (*it)->velocity);
00086
00087
00088 steeringSeparation *= separationWeight;
00089 (*it)->velocity += steeringSeparation;
00090 steeringAlignment *= ((f32) alignmnetWeight) / 100.0f;
00091 (*it)->velocity += steeringAlignment;
00092 steeringCohesion *= cohesionWeight;
00093 (*it)->velocity += steeringCohesion;
00094 steeringSeekTarget *= ((f32) seekTargetWeight) / 1000.0f;
00095 (*it)->velocity += steeringSeekTarget;
00096 }
00097 }
00098
00099 void FlockAnimatorDefault::animateNode(ISceneNode* node, u32 timeMs)
00100 {
00101
00102 testSpeedUp(node);
00103 return;
00104
00105
00106
00107
00108 Flock* f = ((Flock*) node);
00109 list<Boid*>::Iterator it = f->getBoidList().begin();
00110 for (; it != f->getBoidList().end(); ++it)
00111 {
00112
00113 s32 radius = f->getNeighborRadius();
00114
00115 vector3df sep = steerForSeparation((*it), f, radius, 50);
00116 sep *= f->getSeparationWeight();
00117 (*it)->velocity += sep;
00118
00119 vector3df alg = steerForAlignment((*it), f, radius, 50);
00120 alg *= (f32) ((f32) f->getAlignmentWeight()) / 100.0f;
00121 (*it)->velocity += alg;
00122
00123 vector3df coh = steerForCohesion((*it), f, radius, 50);
00124 coh *= f->getCohesionWeight();
00125 (*it)->velocity += coh;
00126
00127
00128 vector3df sek = steerForSeek((*it), f);
00129 sek *= (f32) ((f32) f->getSeekTargetWeight()) / 1000.0f;
00130 (*it)->velocity += sek;
00131 }
00132 }
00133
00134 vector3df FlockAnimatorDefault::steerForSeparation(Boid* boid, Flock* flock, f32 maxDistance, f32 cosMaxAngle)
00135 {
00136
00137 vector3df steering;
00138 s32 neighbors = 0;
00139
00140
00141 list<Boid*>::Iterator it = flock->getBoidList().begin();
00142 for (; it != flock->getBoidList().end(); ++it)
00143 {
00144 if (boid->inBoidNeighborhood((*it), flock->getNeighborRadius() , maxDistance, cosMaxAngle))
00145 {
00146
00147
00148
00149 vector3df offset = (*it)->position - boid->position;
00150 f32 distanceSquared = offset.dotProduct(offset);
00151 steering += (offset / -distanceSquared);
00152
00153
00154 neighbors++;
00155 }
00156 }
00157
00158 if (neighbors > 0)
00159 {
00160 steering = (steering / (f32) neighbors).normalize();
00161 }
00162
00163
00164
00165 return steering;
00166 }
00167
00168 vector3df FlockAnimatorDefault::steerForAlignment(Boid* boid, Flock* flock, f32 maxDistance, f32 cosMaxAngle)
00169 {
00170
00171 vector3df steering;
00172 s32 neighbors = 0;
00173
00174
00175 list<Boid*>::Iterator it = flock->getBoidList().begin();
00176 for (; it != flock->getBoidList().end(); ++it)
00177 {
00178 if (boid->inBoidNeighborhood((*it), flock->getNeighborRadius(), maxDistance, cosMaxAngle))
00179 {
00180
00181 steering += (*it)->forward;
00182
00183
00184 neighbors++;
00185 }
00186 }
00187
00188
00189
00190 if (neighbors > 0)
00191 {
00192 steering = ((steering / (f32) neighbors) - boid->forward).normalize();
00193 }
00194
00195 return steering;
00196 }
00197
00198 vector3df FlockAnimatorDefault::steerForCohesion(Boid* boid, Flock* flock, f32 maxDistance, f32 cosMaxAngle)
00199 {
00200
00201 vector3df steering;
00202 s32 neighbors = 0;
00203
00204
00205 list<Boid*>::Iterator it = flock->getBoidList().begin();
00206 for (; it != flock->getBoidList().end(); ++it)
00207 {
00208 if (boid->inBoidNeighborhood((*it), flock->getNeighborRadius(), maxDistance, cosMaxAngle))
00209 {
00210
00211 steering += (*it)->position;
00212
00213
00214 neighbors++;
00215 }
00216 }
00217
00218
00219
00220 if (neighbors > 0)
00221 {
00222 steering = ((steering / (f32) neighbors) - boid->position).normalize();
00223 }
00224
00225 return steering;
00226 }
00227
00228 vector3df FlockAnimatorDefault::steerForSeek(Boid* boid, Flock* flock)
00229 {
00230 vector3df desiredVelocity = flock->getTarget() - boid->position;
00231 return (desiredVelocity - boid->velocity);
00232 }
00233