flockanimatordefault.cpp

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     // ctor
00015     device = d;
00016     dbg->log("create FlockAnimatorDefault");
00017 }
00018 
00019 FlockAnimatorDefault::~FlockAnimatorDefault()
00020 {
00021     // dtor
00022     dbg->log("FlockAnimatorDefault deleted");
00023 }
00024 
00025 void FlockAnimatorDefault::testSpeedUp(ISceneNode* node)
00026 {
00027     // testing algo
00028     // bring all three iterations together to only one
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     // for each Boid in Flock
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         // for each Boid in Flock
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                 // separation
00061                 vector3df offset = (*it2)->position - (*it)->position;
00062                 f32 distanceSquared = offset.dotProduct(offset);
00063                 steeringSeparation += (offset / -distanceSquared);
00064                 // alignmnet
00065                 steeringAlignment += (*it2)->forward;
00066                 // cohesion
00067                 steeringCohesion += (*it2)->position;
00068 
00069                 neighbors++;
00070             }
00071         }
00072 
00073         if (neighbors > 0)
00074         {
00075             // separation
00076             steeringSeparation = (steeringSeparation / (f32) neighbors).normalize();
00077             // alignmnet
00078             steeringAlignment = ((steeringAlignment / (f32) neighbors) - (*it)->forward).normalize();
00079             // cohesion
00080             steeringCohesion = ((steeringCohesion / (f32) neighbors) - (*it)->position).normalize();
00081         }
00082 
00083         // seek target
00084         vector3df desiredVelocity = seekTarget - (*it)->position;
00085         steeringSeekTarget = (desiredVelocity - (*it)->velocity);
00086 
00087         // multiply steering with its weights and set Boid velocity
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     // debug
00102     testSpeedUp(node);
00103     return;
00104 
00105     // old code down to end of this file !!!!!!!!!!!!!!!!!
00106 
00107     // for each Boid in Flock
00108     Flock* f = ((Flock*) node);
00109     list<Boid*>::Iterator it = f->getBoidList().begin();
00110     for (; it != f->getBoidList().end(); ++it)
00111     {
00112         // apply all three default rules:
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         // apply addition seekness
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     // steering accumulator and count of neighbors, both initially zero
00137     vector3df steering;
00138     s32 neighbors = 0;
00139 
00140     // for each Boid in Flock
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             // add in steering contribution
00147             // (opposite of the offset direction, divided once by distance
00148             // to normalize, divided another time to get 1/d falloff)
00149             vector3df offset = (*it)->position - boid->position;
00150             f32 distanceSquared = offset.dotProduct(offset);
00151             steering += (offset / -distanceSquared);
00152 
00153             // count neighbors
00154             neighbors++;
00155         }
00156     }
00157     // divide by neighbors, then normalize to pure direction
00158     if (neighbors > 0)
00159     {
00160         steering = (steering / (f32) neighbors).normalize();
00161     }
00162 
00163     //boid->addDebugText("neighbors", neighbors);
00164 
00165     return steering;
00166 }
00167 
00168 vector3df FlockAnimatorDefault::steerForAlignment(Boid* boid, Flock* flock, f32 maxDistance, f32 cosMaxAngle)
00169 {
00170     // steering accumulator and count of neighbors, both initially zero
00171     vector3df steering;
00172     s32 neighbors = 0;
00173 
00174     // for each Boid in Flock
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             // accumulate sum of neighbor's heading
00181             steering += (*it)->forward;
00182 
00183             // count neighbors
00184             neighbors++;
00185         }
00186     }
00187 
00188     // divide by neighbors, subtract off current heading to get error-
00189     // correcting direction, then normalize to pure direction
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     // steering accumulator and count of neighbors, both initially zero
00201     vector3df steering;
00202     s32 neighbors = 0;
00203 
00204     // for each Boid in Flock
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             // accumulate sum of neighbor's positions
00211             steering += (*it)->position;
00212 
00213             // count neighbors
00214             neighbors++;
00215         }
00216     }
00217 
00218     // divide by neighbors, subtract off current position to get error-
00219     // correcting direction, then normalize to pure direction
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 

Generated on Sun Dec 2 17:09:57 2007 for Swarm by  doxygen 1.4.6-NO