Boids.cpp
上传用户:wymy58
上传日期:2007-01-07
资源大小:2086k
文件大小:19k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. // Boids.cpp : Defines the class behaviors for the application.
  2. #include "stdafx.h"
  3. #include "Boids.h"
  4. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #undef THIS_FILE
  7. static char THIS_FILE[] = __FILE__;
  8. #endif
  9. const bool g_bFullScreen
  10. #ifdef _DEBUG
  11. = false; // true;
  12. #else
  13. = true; // false;
  14. #endif // _DEBUG
  15. const bool g_bUseZBuffer = true; // false;
  16. const DWORD g_dwWidth = 640; // 800; // 1024;
  17. const DWORD g_dwHeight = 480; // 600; // 768;
  18. const DWORD g_dwBPP = 16; // 32;
  19. const bool g_bUseVoodoo12 = false; // true;
  20. const _GUID* const g_lpGuidD3DDevice
  21. = NULL;
  22. // = &IID_IDirect3DTnLHalDevice;
  23. // = &IID_IDirect3DRGBDevice;
  24. // = &IID_IDirect3DHALDevice;
  25. // = &IID_IDirect3DRefDevice;
  26. #define NUM_BOIDS 13
  27. #define NUM_OBSTACLES 8
  28. #define OBSTACLE_RADIUS 3.0f
  29. #define NUM_GRID 20
  30. #define GRID_WIDTH 190.0
  31. D3DVERTEX pvGridVertices[NUM_GRID * NUM_GRID];
  32. D3DVERTEX m_pvBoidVertices[16];
  33. WORD pwBoidIndices[30];
  34. CBoidsApp::CBoidsApp(void)
  35. {
  36. m_dwAppInitFlags &= ~CDirectXApp::DXAPPIF_DD;
  37. m_dwAppInitFlags |= CDirectXApp::DXAPPIF_D3DIM;
  38. SetFullScreen(g_bFullScreen);
  39. SetPackFileName(_T("Data"), _T("gui"));
  40. // Called during initial app startup, this function
  41. // performs all the permanent initialization.
  42. m_pD3DDevice = NULL;
  43. m_pD3DMaterial = NULL;
  44. // add your permanent init code here !
  45. m_pLight1 = m_pLight2 = NULL;
  46. m_pTexture = NULL;
  47. // generate the sphere data
  48. m_pSphere = new  CD3DSphere(OBSTACLE_RADIUS, 10);
  49. }
  50. // Called before the app exits, this function gives the app
  51. // the chance to cleanup after itself.
  52. CBoidsApp::~CBoidsApp()
  53. {
  54. // add your cleaup code here !
  55. if (m_pSphere != NULL)
  56. {
  57. delete  m_pSphere;
  58. m_pSphere = NULL;
  59. }
  60. }
  61. bool CBoidsApp::GetDXInitSettings(void)
  62. {
  63. if (m_pDirectSound != NULL)
  64. {
  65. if (m_pDirectSound->SelectDSDriver(0) == false)
  66. return  false;
  67. }
  68. if (m_pDirectMusic != NULL)
  69. {
  70. if (m_pDirectMusic->SelectDefaultDMusPort() == false)
  71. return  false;
  72. }
  73. if ((g_bUseVoodoo12 == false)
  74. || m_pDirectDraw->SelectDDDevice(0, 1) == false)
  75. {
  76. if (m_pDirectDraw->SelectDDDevice(0) == false)
  77. return  false;
  78. }
  79. if (g_bUseZBuffer)
  80. m_dwDDInitFlags |= CDDDevice::D3DIF_ZBUFFER;
  81. if (GetFirstDDDevice()->IsCanRenderWindowed() == false)
  82. {
  83. m_dwDDInitFlags &= ~CDDDevice::DDIF_WINDOWED;
  84. m_dwDDInitFlags &= ~CDDDevice::DDIF_NO_FLIP;
  85. }
  86. else
  87. {
  88. m_dwDDInitFlags |= CDDDevice::DDIF_NO_FLIP;
  89. }
  90. if (g_lpGuidD3DDevice == NULL)
  91. {
  92. if (GetFirstDDDevice()->SelectDefaultD3DDevice() == false)
  93. return  false;
  94. }
  95. else
  96. {
  97. if (GetFirstDDDevice()->SelectD3DDevice(g_lpGuidD3DDevice) == false)
  98. return  false;
  99. }
  100. if (GetFirstDDDevice()->SelectDisplayMode(
  101. IsFullScreen(), g_dwWidth, g_dwHeight, g_dwBPP) == false)
  102. return  false;
  103. return  true;
  104. }
  105. // Structure for holding data for each boid
  106. struct Boid
  107. {
  108. D3DVECTOR dvLoc;
  109. D3DVECTOR dvDir; // Current direction
  110. D3DVECTOR dvDeltaPos; // Change in position from flock centering
  111. D3DVECTOR dvDeltaDir; // Change in direction
  112. WORD wDeltaCnt; // Number of boids that influence this dvDeltaDir
  113. FLOAT fSpeed;
  114. FLOAT fYaw, fPitch, fRoll, fDYaw;
  115. FLOAT r, g, b; // Color of the boid
  116. FLOAT afDist[NUM_BOIDS]; // Array of boid distances, yuk what a waste
  117. CD3DMatrix matLocal;
  118. };
  119. Boid      g_pBoids[NUM_BOIDS];
  120. D3DVECTOR g_vObstacleLocations[NUM_OBSTACLES];
  121. D3DVECTOR g_vGoal;
  122. CD3DMatrix g_matGrid;
  123. const FLOAT InfluenceRadius        = 20.0f;
  124. const FLOAT InfluenceRadiusSquared = InfluenceRadius * InfluenceRadius;
  125. const FLOAT CollisionFraction      = 0.8f;
  126. const FLOAT InvCollisionFraction   = 1.0f/(1.0f-CollisionFraction);
  127. const FLOAT NormalSpeed            = 0.1f;
  128. const FLOAT AngleTweak             = 0.02f;
  129. const FLOAT PitchToSpeedRatio      = 0.002f;
  130. // Called during device intialization, this code checks the device
  131. // for some minimum set of capabilities, Initialize scene objects.
  132. bool CBoidsApp::InitDXObjects(void)
  133. {
  134. m_pD3DDevice = GetFirstD3DDevice();
  135. ASSERT(m_pD3DDevice != NULL);
  136. m_pD3DMaterial = m_pD3DDevice->GetD3DMaterial();
  137. // add your init code here !
  138. g_vGoal = D3DVECTOR(0.0f, 0.0f, 0.0f);
  139. for (WORD  i = 0; i < NUM_BOIDS; ++ i)
  140. {
  141. g_pBoids[i].dvLoc = D3DVECTOR(100.0f*(CDirectX::rnd()-CDirectX::rnd()), 10.0f*CDirectX::rnd(), 100.0f*(CDirectX::rnd()-CDirectX::rnd()));
  142. g_pBoids[i].dvDir = Normalize(D3DVECTOR(CDirectX::rnd()-CDirectX::rnd(), CDirectX::rnd()-CDirectX::rnd(), CDirectX::rnd()-CDirectX::rnd()));
  143. g_pBoids[i].fYaw = 0.0f;
  144. g_pBoids[i].fPitch = 0.0f;
  145. g_pBoids[i].fRoll  = 0.0f;
  146. g_pBoids[i].fDYaw  = 0.0f;
  147. g_pBoids[i].fSpeed = 0.1f;
  148. g_pBoids[i].r = CDirectX::rnd();
  149. g_pBoids[i].g = CDirectX::rnd();
  150. g_pBoids[i].b = CDirectX::rnd();
  151. FLOAT fMin = min( g_pBoids[i].r, min( g_pBoids[i].g, g_pBoids[i].b ) );
  152. FLOAT fMax = max( g_pBoids[i].r, min( g_pBoids[i].g, g_pBoids[i].b ) );
  153. g_pBoids[i].r = (g_pBoids[i].r - fMin) / (fMax-fMin);
  154. g_pBoids[i].g = (g_pBoids[i].g - fMin) / (fMax-fMin);
  155. g_pBoids[i].b = (g_pBoids[i].b - fMin) / (fMax-fMin);
  156. }
  157. // Position the obstacles
  158. g_vObstacleLocations[0] = D3DVECTOR( 100, 10,    0 );
  159. g_vObstacleLocations[1] = D3DVECTOR(-100, 10,    0 );
  160. g_vObstacleLocations[2] = D3DVECTOR(   0, 10,  100 );
  161. g_vObstacleLocations[3] = D3DVECTOR(   0, 10, -100 );
  162. for( i=4; i<NUM_OBSTACLES; i++ )
  163. g_vObstacleLocations[i] = D3DVECTOR( 100*(CDirectX::rnd()-CDirectX::rnd()), 10*CDirectX::rnd(), 100*(CDirectX::rnd()-CDirectX::rnd()) );
  164. FLOAT fSize   = GRID_WIDTH/(NUM_GRID-1.0f);
  165. FLOAT fOffset = GRID_WIDTH/2.0f;
  166. for (i = 0; i < NUM_GRID; ++ i)
  167. {
  168. for (WORD  j = 0; j < NUM_GRID; ++ j)
  169. {
  170. pvGridVertices[j+i*NUM_GRID] = D3DVERTEX( 
  171. D3DVECTOR( i*fSize-fOffset, 0.0f, j*fSize-fOffset ),
  172. D3DVECTOR( 0.0f, 1.0f, 0.0f ), 0.0f, 0.0f );
  173. }
  174. }
  175. // Points and normals which make up a boid geometry
  176. D3DVECTOR p1 = D3DVECTOR( 0.00f, 0.00f, 0.50f );
  177. D3DVECTOR p2 = D3DVECTOR( 0.50f, 0.00f,-0.50f );
  178. D3DVECTOR p3 = D3DVECTOR( 0.15f, 0.15f,-0.35f );
  179. D3DVECTOR p4 = D3DVECTOR(-0.15f, 0.15f,-0.35f );
  180. D3DVECTOR p5 = D3DVECTOR( 0.15f,-0.15f,-0.35f );
  181. D3DVECTOR p6 = D3DVECTOR(-0.15f,-0.15f,-0.35f );
  182. D3DVECTOR p7 = D3DVECTOR(-0.50f, 0.00f,-0.50f );
  183. D3DVECTOR n1 = ::Normalize( D3DVECTOR( 0.2f, 1.0f, 0.0f ) );
  184. D3DVECTOR n2 = ::Normalize( D3DVECTOR( 0.1f, 1.0f, 0.0f ) );
  185. D3DVECTOR n3 = Normalize( D3DVECTOR( 0.0f, 1.0f, 0.0f ) );
  186. D3DVECTOR n4 = Normalize( D3DVECTOR(-0.1f, 1.0f, 0.0f ) );
  187. D3DVECTOR n5 = Normalize( D3DVECTOR(-0.2f, 1.0f, 0.0f ) );
  188. D3DVECTOR n6 = Normalize( D3DVECTOR(-0.4f, 0.0f, -1.0f ) );
  189. D3DVECTOR n7 = Normalize( D3DVECTOR(-0.2f, 0.0f, -1.0f ) );
  190. D3DVECTOR n8 = Normalize( D3DVECTOR( 0.2f, 0.0f, -1.0f ) );
  191. D3DVECTOR n9 = Normalize( D3DVECTOR( 0.4f, 0.0f, -1.0f ) );
  192. // Vertices for the top
  193. m_pvBoidVertices[ 0] = D3DVERTEX( p1, n1, 0.000f, 0.500f );
  194. m_pvBoidVertices[ 1] = D3DVERTEX( p2, n2, 0.500f, 1.000f );
  195. m_pvBoidVertices[ 2] = D3DVERTEX( p3, n3, 0.425f, 0.575f );
  196. m_pvBoidVertices[ 3] = D3DVERTEX( p4, n4, 0.425f, 0.425f );
  197. m_pvBoidVertices[ 4] = D3DVERTEX( p7, n5, 0.500f, 0.000f );
  198. // Vertices for the bottom
  199. m_pvBoidVertices[ 5] = D3DVERTEX( p1, -n5, 1.000f, 0.500f );
  200. m_pvBoidVertices[ 6] = D3DVERTEX( p2, -n4, 0.500f, 1.000f );
  201. m_pvBoidVertices[ 7] = D3DVERTEX( p5, -n3, 0.575f, 0.575f );
  202. m_pvBoidVertices[ 8] = D3DVERTEX( p6, -n2, 0.575f, 0.425f );
  203. m_pvBoidVertices[ 9] = D3DVERTEX( p7, -n1, 0.500f, 0.000f );
  204. // Vertices for the  rear
  205. m_pvBoidVertices[10] = D3DVERTEX( p2, n6, 0.500f, 1.000f );
  206. m_pvBoidVertices[11] = D3DVERTEX( p3, n7, 0.425f, 0.575f );
  207. m_pvBoidVertices[12] = D3DVERTEX( p4, n8, 0.425f, 0.425f );
  208. m_pvBoidVertices[13] = D3DVERTEX( p7, n9, 0.500f, 0.000f );
  209. m_pvBoidVertices[14] = D3DVERTEX( p6, n8, 0.575f, 0.425f );
  210. m_pvBoidVertices[15] = D3DVERTEX( p5, n7, 0.575f, 0.575f );
  211. // Vertex inidices for the boid
  212. pwBoidIndices[ 0] =  0;
  213. pwBoidIndices[ 1] =  1;
  214. pwBoidIndices[ 2] =  2;
  215. pwBoidIndices[ 3] =  0;
  216. pwBoidIndices[ 4] =  2;
  217. pwBoidIndices[ 5] =  3;
  218. pwBoidIndices[ 6] =  0;
  219. pwBoidIndices[ 7] =  3;
  220. pwBoidIndices[ 8] =  4;
  221. pwBoidIndices[ 9] =  5;
  222. pwBoidIndices[10] =  7;
  223. pwBoidIndices[11] =  6;
  224. pwBoidIndices[12] =  5;
  225. pwBoidIndices[13] =  8;
  226. pwBoidIndices[14] =  7;
  227. pwBoidIndices[15] =  5;
  228. pwBoidIndices[16] =  9;
  229. pwBoidIndices[17] =  8;
  230. pwBoidIndices[18] = 10;
  231. pwBoidIndices[19] = 15;
  232. pwBoidIndices[20] = 11;
  233. pwBoidIndices[21] = 11;
  234. pwBoidIndices[22] = 15;
  235. pwBoidIndices[23] = 12;
  236. pwBoidIndices[24] = 12;
  237. pwBoidIndices[25] = 15;
  238. pwBoidIndices[26] = 14;
  239. pwBoidIndices[27] = 12;
  240. pwBoidIndices[28] = 14;
  241. pwBoidIndices[29] = 13;
  242. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x0A0A0A0A);
  243. m_pTexture = new  CD3DTexture;
  244. if (m_pTexture->Create(m_pD3DDevice, _T("EARTH.BMP"), m_pPackFileManager, 0, 0) == false)
  245. return  false;
  246. m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  247. m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  248. m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  249. m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
  250. m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
  251. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, true);
  252. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, false);
  253. CD3DMatrix matProj;
  254. FLOAT fAspect = ((FLOAT)m_pD3DDevice->GetHeight()) / m_pD3DDevice->GetWidth();
  255. matProj.SetProjection(/*0.75f*/0.9f, fAspect, 1.0f, 1000.0f);
  256. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj);
  257. m_pLight1 = new  CD3DDirectionalLight(-0.5f, -1.0f, -.3f);
  258. if (m_pLight1->Create(m_pD3DDevice) == false)
  259. return  false;
  260. if (m_pLight1->Enable(true) == false)
  261. return  false;
  262. D3DCOLORVALUE dcvLight2 = {0.5f, 0.5f, 0.5f, 0.0f};
  263. m_pLight2 = new  CD3DDirectionalLight(
  264. D3DVECTOR(0.5f, 1.0f, .3f),
  265. dcvLight2);
  266. if (m_pLight2->Create(m_pD3DDevice) == false)
  267. return  false;
  268. if (m_pLight2->Enable(true) == false)
  269. return  false;
  270. ASSERT(m_pD3DDevice->GetActiveLightsNumber() == 2);
  271. return  true;
  272. }
  273. // Called when the app is exitting, or the device is being changed,
  274. // this function deletes any device dependant objects.
  275. bool CBoidsApp::DestroyDXObjects(void)
  276. {
  277. // add your destroy code here !
  278. if (m_pTexture != NULL)
  279. {
  280. delete  m_pTexture;
  281. m_pTexture = NULL;
  282. }
  283. if (m_pLight1 != NULL)
  284. {
  285. delete  m_pLight1;
  286. m_pLight1 = NULL;
  287. }
  288. if (m_pLight2 != NULL)
  289. {
  290. delete  m_pLight2;
  291. m_pLight2 = NULL;
  292. }
  293. m_pD3DMaterial = NULL;
  294. m_pD3DDevice = NULL;
  295. return  CDirectXApp::DestroyDXObjects();
  296. }
  297. // Update posiiton of each boid in flock
  298. VOID UpdateFlock()
  299. {
  300. // first update the dist array 0.0..1.0 with 0.0 being furthest away
  301. for (WORD  i = 0; i < NUM_BOIDS; ++ i)
  302. {
  303. for (WORD  j = i + 1; j < NUM_BOIDS; ++ j)
  304. {
  305. FLOAT fDist = SquareMagnitude(g_pBoids[i].dvLoc - g_pBoids[j].dvLoc);
  306. fDist = InfluenceRadiusSquared - fDist;
  307. if( fDist < 0.0f )
  308. fDist = 0.0f;
  309. else
  310. fDist /= InfluenceRadiusSquared;
  311. g_pBoids[i].afDist[j] = g_pBoids[j].afDist[i] = fDist;
  312. }
  313. g_pBoids[i].afDist[i] = 0.0f;
  314. g_pBoids[i].dvDeltaDir = D3DVECTOR(0.0f, 0.0f, 0.0f);
  315. g_pBoids[i].dvDeltaPos = D3DVECTOR(0.0f, 0.0f, 0.0f);
  316. g_pBoids[i].wDeltaCnt = 0;
  317. }
  318. for (i = 0; i < NUM_BOIDS; ++ i)
  319. {
  320. for (WORD  j = i + 1; j < NUM_BOIDS; ++ j)
  321. {
  322. // if i is near j have them influence each other
  323. if (g_pBoids[i].afDist[j] > 0.0f)
  324. {
  325. D3DVECTOR vDiff = Normalize(g_pBoids[i].dvLoc - g_pBoids[j].dvLoc);
  326. D3DVECTOR vDelta;
  327. FLOAT fCollWeight = 0.0f; // collision weighting
  328. // only do collision testing against the nearest ones
  329. if (g_pBoids[i].afDist[j] - CollisionFraction > 0.0f)
  330. fCollWeight = (g_pBoids[i].afDist[j] - CollisionFraction) * InvCollisionFraction;
  331. // add in a little flock centering
  332. if (g_pBoids[i].afDist[j] - (1.0f-CollisionFraction) > 0.0f)
  333. fCollWeight -= g_pBoids[i].afDist[j] * (1.0f - fCollWeight);
  334. vDelta = fCollWeight * vDiff;
  335. // add in the collision avoidance
  336. g_pBoids[i].dvDeltaPos += vDelta;
  337. g_pBoids[j].dvDeltaPos -= vDelta;
  338. // add in the velocity influences
  339. g_pBoids[i].dvDeltaDir += g_pBoids[j].dvDir * g_pBoids[i].afDist[j];
  340. g_pBoids[j].dvDeltaDir += g_pBoids[i].dvDir * g_pBoids[i].afDist[j];
  341. g_pBoids[i].wDeltaCnt++;
  342. g_pBoids[j].wDeltaCnt++;
  343. }
  344. }
  345. }
  346. // update the boids
  347. for (i = 0; i < NUM_BOIDS; ++ i)
  348. {
  349. if (g_pBoids[i].wDeltaCnt)
  350. {
  351. g_pBoids[i].dvDeltaDir /= (FLOAT)g_pBoids[i].wDeltaCnt;
  352. g_pBoids[i].dvDeltaDir -= g_pBoids[i].dvDir;
  353. g_pBoids[i].dvDeltaDir *= 1.5f;
  354. }
  355. D3DVECTOR vDelta = g_pBoids[i].dvDeltaDir + g_pBoids[i].dvDeltaPos;
  356. D3DVECTOR vOffset;
  357. // add in the influence of the global goal
  358. D3DVECTOR vGoal = 0.5 * Normalize(g_vGoal - g_pBoids[i].dvLoc);
  359. vDelta += vGoal;
  360. // add in any obstacles
  361. for (WORD  j = 0; j < NUM_OBSTACLES; ++ j)
  362. {
  363. D3DVECTOR vOb = g_pBoids[i].dvLoc - g_vObstacleLocations[j];
  364. FLOAT fDist = Magnitude(vOb);
  365. if (fDist > 2 * OBSTACLE_RADIUS)
  366. continue;
  367. vOb /= fDist; // normalize
  368. fDist = 1.0f - fDist / (2 * OBSTACLE_RADIUS);
  369. vDelta += fDist * vOb * 5.0f;
  370. }
  371. // first deal with pitch changes
  372. if (vDelta.y > 0.01f)
  373. { // we're too low
  374. g_pBoids[i].fPitch += AngleTweak;
  375. if (g_pBoids[i].fPitch > 0.8f)
  376. g_pBoids[i].fPitch = 0.8f;
  377. }
  378. else if (vDelta.y < -0.01f)
  379. {   // we're too high
  380. g_pBoids[i].fPitch -= AngleTweak;
  381. if (g_pBoids[i].fPitch < -0.8f)
  382. g_pBoids[i].fPitch = -0.8f;
  383. else
  384. {
  385. // add damping
  386. g_pBoids[i].fPitch *= 0.98f;
  387. }
  388. // speed up or slow down depending on angle of attack
  389. g_pBoids[i].fSpeed -= g_pBoids[i].fPitch * PitchToSpeedRatio;
  390. // damp back to normal
  391. g_pBoids[i].fSpeed = (g_pBoids[i].fSpeed-NormalSpeed)*0.99f + NormalSpeed;
  392. if( g_pBoids[i].fSpeed < NormalSpeed/2 )
  393. g_pBoids[i].fSpeed = NormalSpeed/2;
  394. if( g_pBoids[i].fSpeed > NormalSpeed*5 )
  395. g_pBoids[i].fSpeed = NormalSpeed*5;
  396. // now figure out yaw changes
  397. vOffset = vDelta;
  398. vOffset.y = 0.0f;
  399. vDelta = g_pBoids[i].dvDir;
  400. vOffset = Normalize( vOffset );
  401. FLOAT fDot = DotProduct(vOffset, vDelta);
  402. // speed up slightly if not turning much
  403. if( fDot > 0.7f )
  404. {
  405. fDot -= 0.7f;
  406. g_pBoids[i].fSpeed += fDot * 0.005f;
  407. }
  408. vOffset = CrossProduct( vOffset, vDelta );
  409. fDot = (1.0f-fDot)/2.0f * 0.07f;
  410. if( vOffset.y > 0.05f )
  411. g_pBoids[i].fDYaw = (g_pBoids[i].fDYaw*19.0f + fDot) * 0.05f;
  412. else if( vOffset.y < -0.05f )
  413. g_pBoids[i].fDYaw = (g_pBoids[i].fDYaw*19.0f - fDot) * 0.05f;
  414. else
  415. g_pBoids[i].fDYaw *= 0.98f; // damp it
  416. g_pBoids[i].fYaw += g_pBoids[i].fDYaw;
  417. g_pBoids[i].fRoll = -g_pBoids[i].fDYaw * 20.0f;
  418. }
  419. }
  420. // Called once per frame, the call is the entry point for
  421. // animating the scene. This function sets up render states,
  422. // clears the viewport, and renders the scene.
  423. bool CBoidsApp::UpdateFrame(void)
  424. {
  425. // add your code here !
  426. static FLOAT tic = -200.0f * CDirectX::rnd();
  427. tic += 0.01f;
  428. CD3DMatrix matView;
  429. static D3DVECTOR vEyePt( 0.0f, 30.0f, 100.0f );
  430. static D3DVECTOR vLookatPt( 0.0f, 0.0f, 50.0f );
  431. static D3DVECTOR vUpVec( 0.0f, 1.0f, 0.0f );
  432. matView.SetView(vEyePt, vLookatPt, vUpVec);
  433. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &matView);
  434. // Update grid matrix
  435. D3DVECTOR vOffset;
  436. vOffset.x = (FLOAT)floor(vLookatPt.x / 20) * 20.0f - 10.0f;
  437. vOffset.y = 0.0f;
  438. vOffset.z = (FLOAT)floor(vLookatPt.z / 20) * 20.0f - 10.0f;
  439. g_matGrid.SetTranslate(vOffset);
  440. UpdateFlock();
  441. vLookatPt = D3DVECTOR( 0.0f, 0.0f, 0.0f );
  442. // draw the boids
  443. for (WORD  i = 0; i < NUM_BOIDS; ++ i)
  444. {
  445. // Build the world matrix for the boid. First translate into place, 
  446. // then set orientation, then scale (if needed)
  447. CD3DMatrix matWorld;
  448. matWorld.SetTranslate(g_pBoids[i].dvLoc);
  449. CD3DMatrix matRotateY;
  450. matRotateY.SetRotateY(-g_pBoids[i].fYaw);
  451. CD3DMatrix matRotateX;
  452. matRotateX.SetRotateX(-g_pBoids[i].fPitch);
  453. CD3DMatrix matRotateZ;
  454. matRotateZ.SetRotateZ(-g_pBoids[i].fRoll);
  455. CD3DMatrix matTemp = matRotateX * matRotateY;
  456. matTemp = matRotateZ * matTemp;
  457. matWorld = matTemp * matWorld;
  458. g_pBoids[i].matLocal = matWorld;
  459. g_pBoids[i].dvDir.x = matWorld(2, 0);
  460. g_pBoids[i].dvDir.y = matWorld(2, 1);
  461. g_pBoids[i].dvDir.z = matWorld(2, 2);
  462. g_pBoids[i].dvLoc += g_pBoids[i].dvDir * g_pBoids[i].fSpeed;
  463. vLookatPt += g_pBoids[i].dvLoc;
  464. }
  465. vLookatPt /= NUM_BOIDS;
  466. vEyePt.x = vLookatPt.x + (FLOAT)(30.0f * ::sin(tic * 0.223));
  467. vEyePt.y = vLookatPt.y + (FLOAT)(21.0f + 20.0f * ::sin(tic * 0.33f));
  468. vEyePt.z = vLookatPt.z + (FLOAT)(30.0f * ::cos(tic * 0.31f));
  469. g_vGoal.x = 105.0f * (FLOAT)::sin(tic * 0.1f);
  470. g_vGoal.y = 10.0f;
  471. g_vGoal.z = 105.0f * (FLOAT)::cos(tic * 0.1f);
  472. m_pD3DDevice->Clear(RGBA_MAKE(0, 0, 0, 0));
  473. // Begin the scene
  474. if (SUCCEEDED(m_pD3DDevice->BeginScene()))
  475. {
  476. m_pD3DDevice->SetTexture(0, NULL);
  477. // Draw the north-south lines
  478. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &g_matGrid);
  479. m_pD3DDevice->DrawPrimitive(D3DPT_LINELIST, D3DFVF_VERTEX,
  480. pvGridVertices, NUM_GRID * NUM_GRID, 0);
  481. // Draw the east-west lines
  482. CD3DMatrix matRotateY;
  483. matRotateY.SetRotateY(g_PI / 2.0f);
  484. // matRotateY = g_matGrid * matRotateY;
  485. matRotateY *= g_matGrid;
  486. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matRotateY);
  487. m_pD3DDevice->DrawPrimitive(D3DPT_LINELIST, D3DFVF_VERTEX,
  488. pvGridVertices, NUM_GRID*NUM_GRID, 0);
  489. // Draw the boids
  490. for (WORD  i = 0; i < NUM_BOIDS; ++ i)
  491. {
  492. // Set the color for the boid
  493. m_pD3DMaterial->SetColor(g_pBoids[i].r, g_pBoids[i].g, g_pBoids[i].b, 0.0f);
  494. m_pD3DMaterial->Set();
  495. // Apply the boid's local matrix
  496. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &g_pBoids[i].matLocal);
  497. // Draw the boid
  498. m_pD3DDevice->DrawIndexedPrimitive(
  499. D3DPT_TRIANGLELIST, D3DFVF_VERTEX,
  500. m_pvBoidVertices, 16,
  501. pwBoidIndices, 30, 0);
  502. }
  503. // Draw the obstacles
  504. m_pD3DMaterial->SetColor(1.0f, 1.0f, 1.0f, 0.0f);
  505. m_pD3DMaterial->Set();
  506. m_pTexture->SetAsCurrent();
  507. for (i = 0; i < NUM_OBSTACLES; ++ i)
  508. {
  509. CD3DMatrix matWorld;
  510. matWorld.SetTranslate(g_vObstacleLocations[i]);
  511. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
  512. // Draw the obstacle
  513. m_pSphere->Render(m_pD3DDevice);
  514. }
  515. // End the scene.
  516. m_pD3DDevice->EndScene();
  517. }
  518. return  CDirectXApp::UpdateFrame();
  519. }
  520. // ---- add your functions ! ----
  521. // ----
  522. #if _MSC_VER >= 1200 && _MSC_VER < 1400
  523. #ifdef _DEBUG
  524. #pragma comment(lib, "DXGuideD_VC6.lib")
  525. #else
  526. #pragma comment(lib, "DXGuide_VC6.lib")
  527. #endif // _DEBUG
  528. #endif // _MSC_VER
  529. #if _MSC_VER >= 1000 && _MSC_VER < 1200
  530. #ifdef _DEBUG
  531. #pragma comment(lib, "DXGuideD_VC5.lib")
  532. #else
  533. #pragma comment(lib, "DXGuide_VC5.lib")
  534. #endif // _DEBUG
  535. #endif // _MSC_VER
  536. BEGIN_MESSAGE_MAP(CBoidsApp, CDirectXApp)
  537. //{{AFX_MSG_MAP(CBoidsApp)
  538. //}}AFX_MSG_MAP
  539. END_MESSAGE_MAP()
  540. CBoidsApp theApp;