home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / boids / flock.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-15  |  5.9 KB  |  203 lines

  1. /*
  2. **-----------------------------------------------------------------------------
  3. **    File:        flock.cpp 
  4. **    Purpose:    -- where the boids are
  5. **    Notes:
  6. **
  7. **  Copyright (c) 1995 - 1997 by Microsoft, all rights reserved.
  8. **-----------------------------------------------------------------------------
  9. */
  10.  
  11. /*
  12. **-----------------------------------------------------------------------------
  13. ** Include Files
  14. **-----------------------------------------------------------------------------
  15. */
  16.  
  17. #include "Common.h"
  18. #include "Debug.h"
  19. #include "d3dutils.h"
  20. #include "boids.h"
  21.  
  22.  
  23.  
  24. /*
  25. **-----------------------------------------------------------------------------
  26. ** Constants
  27. **-----------------------------------------------------------------------------
  28. */
  29.  
  30. const float InfluenceRadius = 20.0f;
  31. const float InfluenceRadiusSquared = InfluenceRadius * InfluenceRadius;
  32. const float CollisionFraction = 0.8f;
  33. const float InvCollisionFraction = 1.0f/(1.0f-CollisionFraction);
  34.  
  35. const float NormalSpeed = 0.1f;
  36. const float    AngleTweak = 0.02f;
  37. const float PitchToSpeedRatio = 0.002f;
  38.  
  39.  
  40.  
  41. /*
  42. **-----------------------------------------------------------------------------
  43. ** Functions
  44. **-----------------------------------------------------------------------------
  45. */
  46.  
  47. /*
  48. **-----------------------------------------------------------------------------
  49. ** Name:    UpdateFlock
  50. ** Purpose:    Update posiiton of each boid in flock
  51. **-----------------------------------------------------------------------------
  52. */
  53.  
  54. void    
  55. UpdateFlock (Flock flock)
  56. {
  57.     int        i, j;
  58.     float    dist;
  59.  
  60.     // first update the dist array 0.0..1.0 with 0.0 being furthest away
  61.     for (i=0; i<flock.num_boids; i++) {
  62.         for (j=i+1; j<flock.num_boids; j++) {
  63.             dist = SquareMagnitude(flock.boids[i].loc - flock.boids[j].loc);
  64.             dist = InfluenceRadiusSquared - dist;
  65.             if (dist < 0.0f) {
  66.                 dist = 0.0f;
  67.             } else {
  68.                 dist /= InfluenceRadiusSquared;
  69.             }
  70.             flock.dist[i][j] = flock.dist[j][i] = dist;
  71.         }
  72.         flock.dist[i][i] = 0.0f;
  73.         flock.boids[i].delta_dir = D3DVECTOR(0.0f);
  74.         flock.boids[i].delta_pos = D3DVECTOR(0.0f);
  75.         flock.boids[i].delta_cnt = 0;
  76.     }
  77.  
  78.     for (i=0; i<flock.num_boids; i++) {
  79.         for (j=i+1; j<flock.num_boids; j++) {
  80.             // if i is near j have them influence each other
  81.             if (flock.dist[i][j] > 0.0) {
  82.                 D3DVECTOR    diff = Normalize(flock.boids[i].loc - flock.boids[j].loc);
  83.                 D3DVECTOR    delta;
  84.                 float        col = 0.0f;        // collision weighting
  85.  
  86.                 // only do collision testing against the nearest ones
  87.                 if (flock.dist[i][j] - CollisionFraction > 0.0f) {
  88.                     col = (flock.dist[i][j] - CollisionFraction) * InvCollisionFraction;
  89.                 }
  90.  
  91.                 // add in a little flock centering
  92.                 if (flock.dist[i][j] - (1.0-CollisionFraction) > 0.0f) {
  93.                     col -= flock.dist[i][j] * (1.0f-col);
  94.                 }
  95.  
  96.                 delta = col * diff;
  97.  
  98.                 // add in the collision avoidance
  99.                 flock.boids[i].delta_pos += delta;
  100.                 flock.boids[j].delta_pos -= delta;
  101.  
  102.                 // add in the velocity influences
  103.                 flock.boids[i].delta_dir += flock.boids[j].dir * flock.dist[i][j];
  104.                 flock.boids[j].delta_dir += flock.boids[i].dir * flock.dist[i][j];
  105.                 flock.boids[i].delta_cnt++;
  106.                 flock.boids[j].delta_cnt++;
  107.             }
  108.         }
  109.     }
  110.  
  111.     // update the boids
  112.     for (i=0; i<flock.num_boids; i++) {
  113.         if (flock.boids[i].delta_cnt) {
  114.             flock.boids[i].delta_dir /= (float)flock.boids[i].delta_cnt;
  115.             flock.boids[i].delta_dir -= flock.boids[i].dir;
  116.             flock.boids[i].delta_dir *= 1.5f;
  117.         }
  118.         D3DVECTOR    delta = flock.boids[i].delta_dir + flock.boids[i].delta_pos; // + 0.1f * D3DVECTOR(rnd()-rnd(), rnd()-rnd(), rnd()-rnd());
  119.         D3DVECTOR    offset;
  120.  
  121.         //delta = Normalize(delta);
  122.  
  123.         // add in the influence of the global goal
  124.         D3DVECTOR    goal = 0.5f * Normalize(flock.goal-flock.boids[i].loc);
  125.         delta += goal;
  126.  
  127.         // add in any obstacles
  128.         for (j=0; j<flock.num_obs; j++) {
  129.             D3DVECTOR    ob = flock.boids[i].loc - flock.obs[j].loc;
  130.             float        radius = flock.obs[j].radius;
  131.             float        dist = Magnitude(ob);
  132.  
  133.             if (dist > 2*radius)
  134.                 continue;
  135.  
  136.             ob /= dist;    // normalize
  137.             dist = 1.0f - dist/(2.0f*radius);
  138.             delta += dist * ob * 5.0f;
  139.         }
  140.  
  141.         // first deal with pitch changes
  142.         if (delta.y > 0.01) {            // we're too low
  143.             flock.boids[i].pitch += AngleTweak;
  144.             if (flock.boids[i].pitch > 0.8f)
  145.                 flock.boids[i].pitch = 0.8f;
  146.         } else if (delta.y < -0.01) {    // we're too high
  147.             flock.boids[i].pitch -= AngleTweak;
  148.             if (flock.boids[i].pitch < -0.8f)
  149.                 flock.boids[i].pitch = -0.8f;
  150.         } else {
  151.             // add damping
  152.             flock.boids[i].pitch *= 0.98f;
  153.         }
  154.  
  155.         // speed up or slow down depending on angle of attack
  156.         flock.boids[i].speed -= flock.boids[i].pitch * PitchToSpeedRatio;
  157.         // damp back to normal
  158.         flock.boids[i].speed = (flock.boids[i].speed-NormalSpeed)*0.99f + NormalSpeed;
  159.  
  160.         if (flock.boids[i].speed < NormalSpeed/2) {
  161.             flock.boids[i].speed = NormalSpeed/2;
  162.         }
  163.         if (flock.boids[i].speed > NormalSpeed*5) {
  164.             flock.boids[i].speed = NormalSpeed*5;
  165.         }
  166.  
  167.         // now figure out yaw changes
  168.         offset = delta;
  169.         offset.y = 0.0f;
  170.         delta = flock.boids[i].dir;
  171.         offset = Normalize(offset);
  172.         float    dot = DotProduct(offset, delta);
  173.         // speed up slightly if not turning much
  174.         if (dot > 0.7f) {
  175.             dot -= 0.7f;
  176.             flock.boids[i].speed += dot * 0.005f;
  177.         }
  178.         offset = CrossProduct(offset, delta);
  179.         dot = (1.0f-dot)/2.0f * 0.07f;
  180.         if (offset.y > 0.05f) {
  181.             flock.boids[i].dyaw = (flock.boids[i].dyaw*19.0f + dot) * 0.05f;
  182.         } else if (offset.y < -0.05f) {
  183.             flock.boids[i].dyaw = (flock.boids[i].dyaw*19.0f - dot) * 0.05f;
  184.         } else {
  185.             flock.boids[i].dyaw *= 0.98f;    // damp it
  186.         }
  187.         flock.boids[i].yaw += flock.boids[i].dyaw;
  188.         flock.boids[i].roll = -flock.boids[i].dyaw * 20.0f;
  189.  
  190.  
  191.     }
  192.  
  193. }    // end of UpdateFlock()
  194.  
  195.  
  196. /*
  197. **-----------------------------------------------------------------------------
  198. ** End of File
  199. **-----------------------------------------------------------------------------
  200. */
  201.  
  202.  
  203.