BOIDS.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:29k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2. **----------------------------------------------------------------------------
  3. **
  4. **  File:       boids.cpp
  5. **  Purpose:    
  6. **  Notes:
  7. **
  8. ** Copyright (C) 1995 - 1997 Microsoft Corporation. All Rights Reserved.
  9. **----------------------------------------------------------------------------
  10. */
  11. /*
  12. **----------------------------------------------------------------------------
  13. ** Includes
  14. **----------------------------------------------------------------------------
  15. */
  16. #include <math.h>
  17. #include <time.h>
  18. #include "D3DScene.h"
  19. #include "Debug.h"
  20. #include "D3DWin.h"
  21. #include "d3dutils.h"
  22. #include "d3dtex.h"
  23. #include "boids.h"
  24. /*
  25. **----------------------------------------------------------------------------
  26. ** Defines
  27. **----------------------------------------------------------------------------
  28. */
  29. #define NUM_BOIDS 13
  30. // ground pattern
  31. D3DVECTOR       grid_color(0.0f, 0.3f, 0.5f);
  32. D3DLVERTEX pattern1[24];
  33. D3DLVERTEX pattern2[8];
  34. WORD pat1_indices[25] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
  35. 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0 };
  36. WORD pat2_indices[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 0 };
  37. #define MESH_SIZE 8
  38. #define SPHERE_VERTICES (2+MESH_SIZE*MESH_SIZE*2)
  39. #define SPHERE_INDICES ((MESH_SIZE*4 + MESH_SIZE*4*(MESH_SIZE-1))*3)
  40.     
  41. /*
  42. **----------------------------------------------------------------------------
  43. ** Local Variables
  44. **----------------------------------------------------------------------------
  45. */
  46. D3DVERTEX sphere[SPHERE_VERTICES];
  47. WORD sphere_indices[SPHERE_INDICES];
  48. Flock flock;
  49. D3DVERTEX boid_vertices[16];
  50. WORD boid_indices[30];
  51. D3DMATRIX proj, view, world;
  52. Light *lpLight1,
  53. *lpLight2;
  54. Material *lpBackgroundMat,
  55. *lpGridMat,
  56. *lpSphereMat,
  57. *lpBoidMat;
  58. D3DTexture SphereTex;
  59. /*
  60. **----------------------------------------------------------------------------
  61. ** Function definitions
  62. **----------------------------------------------------------------------------
  63. */
  64. /*
  65. **----------------------------------------------------------------------------
  66. ** Name:        DrawBoid
  67. ** Purpose:
  68. **----------------------------------------------------------------------------
  69. */
  70. HRESULT
  71. Drawboid(LPDIRECT3DDEVICE2 lpDev)
  72. {
  73. HRESULT hResult;
  74.         hResult = lpDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, D3DVT_VERTEX, (LPVOID)boid_vertices, 16, boid_indices, 30, D3DDP_WAIT);
  75. return hResult;
  76. } // End DrawBoid
  77. /*
  78. **----------------------------------------------------------------------------
  79. ** Name:        DrawSphere
  80. ** Purpose:
  81. **----------------------------------------------------------------------------
  82. */
  83. HRESULT
  84. DrawSphere(LPDIRECT3DDEVICE2 lpDev)
  85. {
  86. HRESULT hResult;
  87.         hResult = lpDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, D3DVT_VERTEX, (LPVOID)sphere, SPHERE_VERTICES, sphere_indices, SPHERE_INDICES, D3DDP_WAIT);
  88. if (hResult != D3D_OK)
  89. return hResult;
  90. return D3D_OK;
  91. } // End DrawSphere
  92. HRESULT
  93. DrawPattern(LPDIRECT3DDEVICE2 lpDev)
  94. {
  95. HRESULT hResult;
  96. for (int dx= -2; dx<3; dx++) {
  97. for (int dz= -2; dz<3; dz++) {
  98. D3DVECTOR offset(dx*80.0f, 0.0f, dz*80.0f);
  99. world = TranslateMatrix(offset);
  100. hResult = lpDev->SetTransform(D3DTRANSFORMSTATE_WORLD, &world);
  101. if (hResult != D3D_OK) {
  102. REPORTERR(hResult);
  103. return hResult;
  104. }
  105.                         hResult = lpDev->DrawIndexedPrimitive(D3DPT_LINESTRIP, D3DVT_LVERTEX, (LPVOID)pattern1, 24, pat1_indices, 25, D3DDP_WAIT);
  106. if (hResult != D3D_OK) {
  107. REPORTERR(hResult);
  108. return hResult;
  109. }
  110.                         hResult = lpDev->DrawIndexedPrimitive(D3DPT_LINESTRIP, D3DVT_LVERTEX, (LPVOID)pattern2, 8, pat2_indices, 9, D3DDP_WAIT);
  111. if (hResult != D3D_OK) {
  112. REPORTERR(hResult);
  113. return hResult;
  114. }
  115. }
  116. }
  117. return D3D_OK;
  118. } // end of DrawPattern()
  119. /*
  120. **----------------------------------------------------------------------------
  121. ** D3DScene Methods
  122. **----------------------------------------------------------------------------
  123. */
  124. /*
  125. **----------------------------------------------------------------------------
  126. ** Name:        D3DScene::D3DScene
  127. ** Purpose: Default Constructor
  128. **----------------------------------------------------------------------------
  129. */
  130. D3DScene::D3DScene(void)
  131. {
  132. lpd3dWindow = NULL;
  133. } // End D3DScene::D3DScene
  134.   
  135. /*
  136. **----------------------------------------------------------------------------
  137. ** Name:        D3DScene::~D3DScene
  138. ** Purpose: Default Destructor
  139. **----------------------------------------------------------------------------
  140. */
  141. D3DScene::~D3DScene(void)
  142. {
  143. Fini();
  144. lpd3dWindow = NULL;
  145. } // End D3DScene::~D3DScene
  146. /*
  147. **----------------------------------------------------------------------------
  148. ** Name:        D3DScene::Init
  149. ** Purpose: Do all static intialization here
  150. ** Notes: This means all Scene data that isn't dependent on the
  151. ** D3D interface, viewport, or D3D device in some manner
  152. **----------------------------------------------------------------------------
  153. */
  154. HRESULT
  155. D3DScene::Init(LPD3DWindow lpd3dWin)
  156. {
  157. HRESULT hResult;
  158. int i, j;
  159. // Check Parameters
  160. if (! lpd3dWin) {
  161. // Need a valid D3D Window object
  162. hResult = APPERR_INVALIDPARAMS;
  163. REPORTERR(hResult);
  164. return hResult;
  165. }
  166. // Save assocation with D3D Window
  167. lpd3dWindow = lpd3dWin;
  168. // generate the boid data
  169. // top
  170. boid_vertices[ 0] = D3DVERTEX(D3DVECTOR(0.0f, 0.0f, 10.0f), Normalize(D3DVECTOR(0.2f, 1.0f, 0.0f)), 0.0f, 0.5f);
  171. boid_vertices[ 1] = D3DVERTEX(D3DVECTOR(10.0f, 0.0f, -10.0f), Normalize(D3DVECTOR(0.1f, 1.0f, 0.0f)), 0.5f, 1.0f);
  172. boid_vertices[ 2] = D3DVERTEX(D3DVECTOR(3.0f, 3.0f, -7.0f), Normalize(D3DVECTOR(0.0f, 1.0f, 0.0f)), 0.425f, 0.575f);
  173. boid_vertices[ 3] = D3DVERTEX(D3DVECTOR(-3.0f, 3.0f, -7.0f), Normalize(D3DVECTOR(-0.1f, 1.0f, 0.0f)), 0.425f, 0.425f);
  174. boid_vertices[ 4] = D3DVERTEX(D3DVECTOR(-10.0f, 0.0f, -10.0f), Normalize(D3DVECTOR(-0.2f, 1.0f, 0.0f)), 0.5f, 0.0f);
  175. //bottom
  176. boid_vertices[ 5] = D3DVERTEX(D3DVECTOR(0.0f, 0.0f, 10.0f), Normalize(D3DVECTOR(0.2f, -1.0f, 0.0f)), 1.0f, 0.5f);
  177. boid_vertices[ 6] = D3DVERTEX(D3DVECTOR(10.0f, 0.0f, -10.0f), Normalize(D3DVECTOR(0.1f, -1.0f, 0.0f)), 0.5f, 1.0f);
  178. boid_vertices[ 7] = D3DVERTEX(D3DVECTOR(3.0f, -3.0f, -7.0f), Normalize(D3DVECTOR(0.0f, -1.0f, 0.0f)), 0.575f, 0.575f);
  179. boid_vertices[ 8] = D3DVERTEX(D3DVECTOR(-3.0f, -3.0f, -7.0f), Normalize(D3DVECTOR(-0.1f, -1.0f, 0.0f)), 0.575f, 0.425f);
  180. boid_vertices[ 9] = D3DVERTEX(D3DVECTOR(-10.0f, 0.0f, -10.0f), Normalize(D3DVECTOR(-0.2f, -1.0f, 0.0f)), 0.5f, 0.0f);
  181. // rear
  182. boid_vertices[10] = D3DVERTEX(D3DVECTOR(10.0f, 0.0f, -10.0f), Normalize(D3DVECTOR(-0.4f, 0.0f, -1.0f)), 0.5f, 1.0f);
  183. boid_vertices[11] = D3DVERTEX(D3DVECTOR(3.0f, 3.0f, -7.0f), Normalize(D3DVECTOR(-0.2f, 0.0f, -1.0f)), 0.425f, 0.575f);
  184. boid_vertices[12] = D3DVERTEX(D3DVECTOR(-3.0f, 3.0f, -7.0f), Normalize(D3DVECTOR(0.2f, 0.0f, -1.0f)), 0.425f, 0.425f);
  185. boid_vertices[13] = D3DVERTEX(D3DVECTOR(-10.0f, 0.0f, -10.0f), Normalize(D3DVECTOR(0.4f, 0.0f, -1.0f)), 0.5f, 0.0f);
  186. boid_vertices[14] = D3DVERTEX(D3DVECTOR(-3.0f, -3.0f, -7.0f), Normalize(D3DVECTOR(0.2f, 0.0f, -1.0f)), 0.575f, 0.425f);
  187. boid_vertices[15] = D3DVERTEX(D3DVECTOR(3.0f, -3.0f, -7.0f), Normalize(D3DVECTOR(-0.2f, 0.0f, -1.0f)), 0.575f, 0.575f);
  188. // top
  189. boid_indices[ 0] = 0;
  190. boid_indices[ 1] = 1;
  191. boid_indices[ 2] = 2;
  192. boid_indices[ 3] = 0;
  193. boid_indices[ 4] = 2;
  194. boid_indices[ 5] = 3;
  195. boid_indices[ 6] = 0;
  196. boid_indices[ 7] = 3;
  197. boid_indices[ 8] = 4;
  198. // bottom
  199. boid_indices[ 9] = 5;
  200. boid_indices[10] = 7;
  201. boid_indices[11] = 6;
  202. boid_indices[12] = 5;
  203. boid_indices[13] = 8;
  204. boid_indices[14] = 7;
  205. boid_indices[15] = 5;
  206. boid_indices[16] = 9;
  207. boid_indices[17] = 8;
  208. // rear
  209. boid_indices[18] = 10;
  210. boid_indices[19] = 15;
  211. boid_indices[20] = 11;
  212. boid_indices[21] = 11;
  213. boid_indices[22] = 15;
  214. boid_indices[23] = 12;
  215. boid_indices[24] = 12;
  216. boid_indices[25] = 15;
  217. boid_indices[26] = 14;
  218. boid_indices[27] = 12;
  219. boid_indices[28] = 14;
  220. boid_indices[29] = 13;
  221. // scale the boid to be unit length
  222. for (i=0; i<16; i++) {
  223. boid_vertices[i].x /= 20.0f;
  224. boid_vertices[i].y /= 20.0f;
  225. boid_vertices[i].z /= 20.0f;
  226. }
  227. // seed the random number generator
  228. srand(time(NULL));
  229. // allocate the flock
  230. if (!(flock.boids = (Boid *)malloc(NUM_BOIDS * sizeof(Boid)))) {
  231. return FALSE;
  232. }
  233. if (!(flock.dist = (float **)malloc(NUM_BOIDS * sizeof(float *)))) {
  234. return FALSE;
  235. }
  236. flock.num_boids = NUM_BOIDS;
  237. flock.goal = D3DVECTOR(0.0f, 0.0f, 0.0f);
  238. for (i=0; i<flock.num_boids; i++) {
  239. flock.boids[i].loc = D3DVECTOR(100.0f*(rnd()-rnd()), 10.0f*rnd(), 100.0f*(rnd()-rnd()));
  240. flock.boids[i].dir = Normalize(D3DVECTOR(rnd()-rnd(), rnd()-rnd(), rnd()-rnd()));
  241. flock.boids[i].yaw = flock.boids[i].pitch = flock.boids[i].roll = flock.boids[i].dyaw = 0.0f;
  242. flock.boids[i].speed = 0.1f;
  243. flock.boids[i].color = D3DVECTOR(rnd(), rnd(), rnd());
  244. flock.boids[i].color -= D3DVECTOR(Min(flock.boids[i].color));
  245. flock.boids[i].color /= Max(flock.boids[i].color);
  246. if (!(flock.dist[i] = (float *)malloc(NUM_BOIDS * sizeof(float)))) {
  247. return FALSE;
  248. }
  249. }
  250. flock.num_obs = 4;
  251. if (!(flock.obs = (Obstacle *)malloc(flock.num_obs * sizeof(Obstacle)))) {
  252. return FALSE;
  253. }
  254.     flock.obs[0].loc = D3DVECTOR(100.0f, 10.0f, 0.0f);
  255.     flock.obs[1].loc = D3DVECTOR(-100.0f, 10.0f, 0.0f);
  256.     flock.obs[2].loc = D3DVECTOR(0.0f, 10.0f, 100.0f);
  257.     flock.obs[3].loc = D3DVECTOR(0.0f, 10.0f, -100.0f);
  258. flock.obs[0].radius = 3.0f;
  259. flock.obs[1].radius = 3.0f;
  260. flock.obs[2].radius = 3.0f;
  261. flock.obs[3].radius = 3.0f;
  262. D3DCOLOR diffuse = D3DRGB(grid_color[0], grid_color[1], grid_color[2]),
  263. specular = D3DRGB(0.0, 0.0, 0.0);
  264. pattern1[ 0] = D3DLVERTEX(D3DVECTOR(-25.0f, 0.0f, 35.0f), diffuse, specular, 0.0f, 0.0f);
  265. pattern1[ 1] = D3DLVERTEX(D3DVECTOR(-15.0f, 0.0f, 35.0f), diffuse, specular, 0.0f, 0.0f);
  266. pattern1[ 2] = D3DLVERTEX(D3DVECTOR(-5.0f, 0.0f, 25.0f), diffuse, specular, 0.0f, 0.0f);
  267. pattern1[ 3] = D3DLVERTEX(D3DVECTOR(5.0f, 0.0f, 25.0f), diffuse, specular, 0.0f, 0.0f);
  268. pattern1[ 4] = D3DLVERTEX(D3DVECTOR(15.0f, 0.0f, 35.0f), diffuse, specular, 0.0f, 0.0f);
  269. pattern1[ 5] = D3DLVERTEX(D3DVECTOR(25.0f, 0.0f, 35.0f), diffuse, specular, 0.0f, 0.0f);
  270. pattern1[ 6] = D3DLVERTEX(D3DVECTOR(35.0f, 0.0f, 25.0f), diffuse, specular, 0.0f, 0.0f);
  271. pattern1[ 7] = D3DLVERTEX(D3DVECTOR(35.0f, 0.0f, 15.0f), diffuse, specular, 0.0f, 0.0f);
  272. pattern1[ 8] = D3DLVERTEX(D3DVECTOR(25.0f, 0.0f, 5.0f), diffuse, specular, 0.0f, 0.0f);
  273. pattern1[ 9] = D3DLVERTEX(D3DVECTOR(25.0f, 0.0f, -5.0f), diffuse, specular, 0.0f, 0.0f);
  274. pattern1[10] = D3DLVERTEX(D3DVECTOR(35.0f, 0.0f, -15.0f), diffuse, specular, 0.0f, 0.0f);
  275. pattern1[11] = D3DLVERTEX(D3DVECTOR(35.0f, 0.0f, -25.0f), diffuse, specular, 0.0f, 0.0f);
  276. pattern1[12] = D3DLVERTEX(D3DVECTOR(25.0f, 0.0f, -35.0f), diffuse, specular, 0.0f, 0.0f);
  277. pattern1[13] = D3DLVERTEX(D3DVECTOR(15.0f, 0.0f,-35.0f), diffuse, specular, 0.0f, 0.0f);
  278. pattern1[14] = D3DLVERTEX(D3DVECTOR(5.0f, 0.0f, -25.0f), diffuse, specular, 0.0f, 0.0f);
  279. pattern1[15] = D3DLVERTEX(D3DVECTOR(-5.0f, 0.0f, -25.0f), diffuse, specular, 0.0f, 0.0f);
  280. pattern1[16] = D3DLVERTEX(D3DVECTOR(-15.0f, 0.0f,-35.0f), diffuse, specular, 0.0f, 0.0f);
  281. pattern1[17] = D3DLVERTEX(D3DVECTOR(-25.0f, 0.0f,-35.0f), diffuse, specular, 0.0f, 0.0f);
  282. pattern1[18] = D3DLVERTEX(D3DVECTOR(-35.0f, 0.0f, -25.0f), diffuse, specular, 0.0f, 0.0f);
  283. pattern1[19] = D3DLVERTEX(D3DVECTOR(-35.0f, 0.0f, -15.0f), diffuse, specular, 0.0f, 0.0f);
  284. pattern1[20] = D3DLVERTEX(D3DVECTOR(-25.0f, 0.0f, -5.0f), diffuse, specular, 0.0f, 0.0f);
  285. pattern1[21] = D3DLVERTEX(D3DVECTOR(-25.0f, 0.0f, 5.0f), diffuse, specular, 0.0f, 0.0f);
  286. pattern1[22] = D3DLVERTEX(D3DVECTOR(-35.0f, 0.0f, 15.0f), diffuse, specular, 0.0f, 0.0f);
  287. pattern1[23] = D3DLVERTEX(D3DVECTOR(-35.0f, 0.0f, 25.0f), diffuse, specular, 0.0f, 0.0f);
  288. pattern2[ 0] = D3DLVERTEX(D3DVECTOR(-5.0f, 0.0f, 15.0f), diffuse, specular, 0.0f, 0.0f);
  289. pattern2[ 1] = D3DLVERTEX(D3DVECTOR(5.0f, 0.0f, 15.0f), diffuse, specular, 0.0f, 0.0f);
  290. pattern2[ 2] = D3DLVERTEX(D3DVECTOR(15.0f, 0.0f, 5.0f), diffuse, specular, 0.0f, 0.0f);
  291. pattern2[ 3] = D3DLVERTEX(D3DVECTOR(15.0f, 0.0f, -5.0f), diffuse, specular, 0.0f, 0.0f);
  292. pattern2[ 4] = D3DLVERTEX(D3DVECTOR(5.0f, 0.0f, -15.0f), diffuse, specular, 0.0f, 0.0f);
  293. pattern2[ 5] = D3DLVERTEX(D3DVECTOR(-5.0f, 0.0f, -15.0f), diffuse, specular, 0.0f, 0.0f);
  294. pattern2[ 6] = D3DLVERTEX(D3DVECTOR(-15.0f, 0.0f, -5.0f), diffuse, specular, 0.0f, 0.0f);
  295. pattern2[ 7] = D3DLVERTEX(D3DVECTOR(-15.0f, 0.0f, 5.0f), diffuse, specular, 0.0f, 0.0f);
  296. float   dj = pi/(MESH_SIZE+1.0f);
  297. float di = pi/MESH_SIZE;
  298. // generate the sphere data, note the random texture coords
  299. // vertices 0 and 1 are the north and south poles
  300. sphere[0] = D3DVERTEX(D3DVECTOR(0.0f, 1.0f, 0.0f), Normalize(D3DVECTOR(0.0f, 1.0f, 0.0f)), 0.0f, 0.0f);
  301. sphere[1] = D3DVERTEX(D3DVECTOR(0.0f, -1.0f, 0.0f), Normalize(D3DVECTOR(0.0f, -1.0f, 0.0f)), 1.0f, 1.0f);
  302. for (j=0; j<MESH_SIZE; j++) {
  303. for (i=0; i<MESH_SIZE*2; i++) {
  304. D3DVECTOR p;
  305. float u, v;
  306. p.y = (float) cos((j+1) * dj);
  307. p.x = (float) sin(i * di) * (float) sin((j+1) * dj);
  308. p.z = (float) cos(i * di) * (float) sin((j+1) * dj);
  309. u = (float)i/MESH_SIZE;
  310. if (u>1.0f) 
  311. u -= 1.0f;
  312. u = 1.0f - u; // flip so texture is not mirrored
  313. v = (float)j/MESH_SIZE;
  314. sphere[2+i+j*MESH_SIZE*2] = D3DVERTEX(p, p, u, v);
  315. }
  316. }
  317. // now generate the traingle indices
  318. // strip around north pole first
  319. for (i=0; i<MESH_SIZE*2; i++) {
  320. sphere_indices[3*i] = 0;
  321. sphere_indices[3*i+1] = i+2;
  322. sphere_indices[3*i+2] = i+3;
  323. if (i==MESH_SIZE*2-1)
  324. sphere_indices[3*i+2] = 2;
  325. }
  326. // now all the middle strips
  327. int v; // vertex offset
  328. int ind; // indices offset
  329. for (j=0; j<MESH_SIZE-1; j++) {
  330. v = 2+j*MESH_SIZE*2;
  331. ind = 3*MESH_SIZE*2 + j*6*MESH_SIZE*2;
  332. for (i=0; i<MESH_SIZE*2; i++) {
  333. sphere_indices[6*i+ind] = v+i;
  334. sphere_indices[6*i+2+ind] = v+i+1;
  335. sphere_indices[6*i+1+ind] = v+i+MESH_SIZE*2;
  336. sphere_indices[6*i+ind+3] = v+i+MESH_SIZE*2;
  337. sphere_indices[6*i+2+ind+3] = v+i+1;
  338. sphere_indices[6*i+1+ind+3] = v+i+MESH_SIZE*2+1;
  339. if (i==MESH_SIZE*2-1) {
  340. sphere_indices[6*i+2+ind] = v+i+1-2*MESH_SIZE;
  341. sphere_indices[6*i+2+ind+3] = v+i+1-2*MESH_SIZE;
  342. sphere_indices[6*i+1+ind+3] = v+i+MESH_SIZE*2+1-2*MESH_SIZE;
  343. }
  344. }
  345. }
  346. // finally strip around south pole
  347. v = SPHERE_VERTICES-MESH_SIZE*2;
  348. ind = SPHERE_INDICES-3*MESH_SIZE*2;
  349. for (i=0; i<MESH_SIZE*2; i++) {
  350. sphere_indices[3*i+ind] = 1;
  351. sphere_indices[3*i+1+ind] = v+i+1;
  352. sphere_indices[3*i+2+ind] = v+i;
  353. if (i==MESH_SIZE*2-1)
  354. sphere_indices[3*i+1+ind] = v;
  355. }
  356. // Success
  357.     return D3D_OK;
  358. } // End D3DScene::Init
  359.   
  360. /*
  361. **-----------------------------------------------------------------------------
  362. **  Name:       D3DScene::Fini
  363. **  Purpose: Cleanup scene objects
  364. **-----------------------------------------------------------------------------
  365. */
  366. HRESULT D3DScene::Fini(void)
  367. {
  368. Detach();
  369. lpd3dWindow = NULL;
  370. // Success
  371. return D3D_OK;
  372. } // End D3DScene::Fini
  373. /*
  374. **----------------------------------------------------------------------------
  375. ** Name:        D3DScene::Attach
  376. ** Purpose: Attaching to a new D3DWindow object
  377. ** Notes: Need to create and attach all Scene objects dependent upon
  378. ** the D3D interface, viewport, and D3D device here.  
  379. ** For Example:  Textures, Materials, Lights, etc.
  380. **----------------------------------------------------------------------------
  381. */
  382. HRESULT D3DScene::Attach(void)
  383. {
  384. HRESULT hResult;
  385. // Check Initialization
  386. if ((! lpd3dWindow) || (! lpd3dWindow->isValid())) {
  387. // Error, not properly initialized
  388. hResult = APPERR_NOTINITIALIZED;
  389. REPORTERR(hResult);
  390. return hResult;
  391. }
  392. hResult = AttachViewport();
  393. if (hResult != D3D_OK) {
  394. return hResult;
  395. }
  396. // Success
  397. return D3D_OK;
  398. } // End D3DScene::Attach
  399.   
  400. /*
  401. **-----------------------------------------------------------------------------
  402. **  Name:       D3DScene::Detach
  403. **  Purpose: Cleanup all scene objects dependent upon the 
  404. ** D3D Interface, viewport, or D3D device 
  405. **-----------------------------------------------------------------------------
  406. */
  407. HRESULT D3DScene::Detach(void)
  408. {
  409. // Cleanup Viewport
  410. DetachViewport();
  411. // Success
  412. return D3D_OK;
  413. } // End D3DScene::Fini
  414. /*
  415. **----------------------------------------------------------------------------
  416. ** Name:        D3DScene::Render
  417. ** Purpose:
  418. **----------------------------------------------------------------------------
  419. */
  420. HRESULT D3DScene::Render(void)
  421. {
  422. LPDIRECT3DDEVICE2 lpDev;
  423. LPDIRECT3DVIEWPORT2 lpView;
  424. RECT rSrc;
  425. LPD3DRECT lpExtent = NULL;
  426. int i;
  427. HRESULT hResult;
  428. D3DCLIPSTATUS status;
  429. D3DRECT d3dRect;
  430. D3DVECTOR offset;
  431. static D3DVECTOR from(0.0f, 30.0f, 100.0f);
  432. static D3DVECTOR at(0.0f, 0.0f, 50.0f);
  433. static D3DVECTOR up(0.0f, 1.0f, 0.0f);
  434. static float tic = -200.0f * rnd();
  435. // Check Initialization
  436. if ((! lpd3dWindow) || (! lpd3dWindow->isValid ())) {
  437. // Error, not properly initialized
  438. hResult = APPERR_NOTINITIALIZED;
  439. REPORTERR(hResult);
  440. return hResult;
  441. }
  442. lpDev = lpd3dWindow->lpd3dDevice;
  443. lpView  = lpd3dWindow->lpd3dViewport;
  444. lpd3dWindow->GetSurfaceRect(rSrc);
  445. // Double Check
  446. #ifdef DEBUG
  447. if ((! lpDev) || (! lpView))
  448. {
  449. // Error, not initialized properly
  450. hResult = APPERR_NOTINITIALIZED;
  451. REPORTERR(hResult);
  452. return hResult;
  453. }
  454. #endif
  455. //
  456.     // Clear both back and z-buffer.
  457.     //
  458.     // NOTE: Its safe to specify the z-buffer clear flag even if we
  459.     // don't have an attached z-buffer. Direct3D will simply discard
  460.     // the flag if no z-buffer is being used.
  461.     //
  462.     // NOTE: For maximum efficiency we only want to clear those
  463.     // regions of the device surface and z-buffer which we actually
  464.     // rendered to in the last frame. This is the purpose of the
  465.     // array of rectangles and count passed to this function. It is
  466.     // possible to query Direct3D for the regions of the device
  467.     // surface that were rendered to by that execute. The application
  468.     // can then accumulate those rectangles and clear only those
  469.     // regions. However this is a very simple sample and so, for
  470.     // simplicity, we will just clear the entire device surface and
  471.     // z-buffer. Probably not something you wan't to do in a real
  472.     // application.
  473.     ///
  474. d3dRect.lX1 = rSrc.left;
  475. d3dRect.lX2 = rSrc.right;
  476. d3dRect.lY1 = rSrc.top;
  477. d3dRect.lY2 = rSrc.bottom;
  478. hResult = lpView->Clear(1UL, &d3dRect,
  479.  D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
  480. if (hResult != D3D_OK) {
  481. REPORTERR(hResult);
  482. return hResult;
  483. }
  484. if (lpExtent) {
  485. // Calculate exclude region
  486. status.dwFlags = D3DCLIPSTATUS_EXTENTS2;
  487. status.dwStatus = 0;
  488. status.minx = (float)lpExtent->x1;
  489. status.maxx = (float)lpExtent->x2;
  490. status.miny = (float)lpExtent->y1;
  491. status.maxy = (float)lpExtent->y2;
  492. status.minz = 0.0f;
  493. status.maxz = 0.0f;
  494. hResult = lpDev->SetClipStatus(&status);
  495. if (hResult != D3D_OK) {
  496. REPORTERR(hResult);
  497. goto lblCLEANUP;
  498. }
  499. }
  500. // Begin Scene
  501. // Note:  This is complicated by the need to
  502. //   check for lost surfaces and restore
  503. hResult = lpDev->BeginScene();
  504. if (hResult != D3D_OK) {
  505. while (hResult == DDERR_SURFACELOST) {
  506. // Restore surface
  507. while (hResult == DDERR_SURFACELOST) {
  508. hResult = lpd3dWindow->Restore();
  509. }
  510. // Try BeginScene again
  511. hResult = lpDev->BeginScene();
  512. }
  513. if (hResult != D3D_OK) {
  514. REPORTERR(hResult);
  515. return hResult;
  516. }
  517. }
  518.     // Turn off specular highlights
  519.         hResult = lpDev->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE);
  520. if (hResult != D3D_OK) {
  521.         REPORTERR(hResult);
  522. goto lblCLEANUP;
  523. }
  524.     // Turn on Z-buffering
  525. hResult = lpDev->SetRenderState(D3DRENDERSTATE_ZENABLE, 1);
  526. if (hResult != D3D_OK) {
  527.         REPORTERR(hResult);
  528. goto lblCLEANUP;
  529. }
  530. // null out the texture handle
  531.     hResult = lpDev->SetRenderState(D3DRENDERSTATE_TEXTUREHANDLE, 0);
  532.     if (hResult != D3D_OK) {
  533.         REPORTERR(hResult);
  534. goto lblCLEANUP;
  535. }
  536. // turn on dithering
  537.     hResult = lpDev->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE);
  538.     if (hResult != D3D_OK) {
  539.         REPORTERR(hResult);
  540. goto lblCLEANUP;
  541. }
  542. // turn on some ambient light
  543.     hResult = lpDev->SetLightState(D3DLIGHTSTATE_AMBIENT, RGBA_MAKE(10, 10, 10, 10));
  544.     if (hResult != D3D_OK) {
  545.         REPORTERR(hResult);
  546. goto lblCLEANUP;
  547. }
  548. // set the view and projection matrices
  549. tic += 0.01f;
  550. view = ViewMatrix(from, at, up);
  551. proj = ProjectionMatrix(1.0f, 500.0f, pi/4.0f);
  552. hResult = lpDev->SetTransform(D3DTRANSFORMSTATE_VIEW, &view);
  553.     if (hResult != D3D_OK) {
  554.         REPORTERR(hResult);
  555. goto lblCLEANUP;
  556. }
  557. hResult = lpDev->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &proj);
  558.     if (hResult != D3D_OK) {
  559.         REPORTERR(hResult);
  560. goto lblCLEANUP;
  561. }
  562. // draw ground grid
  563. lpGridMat->SetAsCurrent(lpDev);
  564. hResult = DrawPattern(lpDev);
  565.     if (hResult != D3D_OK) {
  566.         REPORTERR(hResult);
  567. goto lblCLEANUP;
  568. }
  569. UpdateFlock(flock);
  570. at = D3DVECTOR(0.0f);
  571. // draw the boids
  572. for (i=0; i<flock.num_boids; i++) {
  573. D3DVECTOR step;
  574. // build the world matrix for the boid
  575. world = MatrixMult(MatrixMult(RotateYMatrix(flock.boids[i].yaw), RotateXMatrix(flock.boids[i].pitch)), RotateZMatrix(flock.boids[i].roll));
  576. // first translate into place, then set orientation, then scale (if needed)
  577. world = TranslateMatrix(flock.boids[i].loc);
  578. world = MatrixMult(world, MatrixMult(MatrixMult(RotateYMatrix(flock.boids[i].yaw), 
  579. RotateXMatrix(flock.boids[i].pitch)), RotateZMatrix(flock.boids[i].roll)));
  580. // apply the world matrix
  581. hResult = lpDev->SetTransform(D3DTRANSFORMSTATE_WORLD, &world);
  582. if (hResult != D3D_OK) {
  583. REPORTERR(hResult);
  584. goto lblCLEANUP;
  585. }
  586. // display the boid
  587. lpBoidMat->SetDiffuse(flock.boids[i].color);
  588. lpBoidMat->SetAsCurrent(lpDev);
  589. hResult = Drawboid(lpDev);
  590. if (hResult != D3D_OK) {
  591. REPORTERR(hResult);
  592. goto lblCLEANUP;
  593. }
  594. flock.boids[i].dir[0] = world(2, 0);
  595. flock.boids[i].dir[1] = world(2, 1);
  596. flock.boids[i].dir[2] = world(2, 2);
  597. flock.boids[i].loc += flock.boids[i].dir * flock.boids[i].speed;
  598. at += flock.boids[i].loc;
  599. }
  600. // find the center of the flock and look there for the next frame
  601. at /= (float)(flock.num_boids);
  602. from = at + D3DVECTOR(20.0f * (float)sin (tic* 0.223f), 
  603.                    16.0f + 15.0f * (float)sin (tic * 0.33f), 
  604.    20.0f * (float)cos (tic * 0.31f));
  605. flock.goal = D3DVECTOR(105.0f * (float)sin (tic * 0.1f), 
  606. 10.0f, 
  607. 105.0f * (float)cos (tic * 0.1f));
  608. // Finally, draw obstacles last since they're transparent.
  609. // Set renderstates to support blending such that the texture
  610. // color is added over the background color.  Also turn Z-write
  611. // off so when two spheres line up you can always see them both.
  612.     if (lpDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE) != D3D_OK)
  613.         return FALSE;
  614.     if (lpDev->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCCOLOR) != D3D_OK)
  615.         return FALSE;
  616.     if (lpDev->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE) != D3D_OK)
  617. return FALSE;
  618.     if (lpDev->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE) != D3D_OK)
  619. return FALSE;
  620. // make sure the texture wraps correctly
  621.     if (lpDev->SetRenderState(D3DRENDERSTATE_WRAPU, TRUE) != D3D_OK)
  622. return FALSE;
  623. lpSphereMat->SetAsCurrent(lpDev);
  624. for (i=0; i<flock.num_obs; i++) {
  625. world = MatrixMult(TranslateMatrix(flock.obs[i].loc), MatrixMult(RotateYMatrix(-tic*pi), ScaleMatrix (flock.obs[i].radius)));
  626. hResult = lpDev->SetTransform(D3DTRANSFORMSTATE_WORLD, &world);
  627. if (hResult != D3D_OK) {
  628. REPORTERR(hResult);
  629. return hResult;
  630. }
  631. hResult = DrawSphere(lpDev);
  632. if (hResult != D3D_OK) {
  633. REPORTERR(hResult);
  634. goto lblCLEANUP;
  635. }
  636. }
  637. // set renderstates back to default
  638.     if (lpDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, FALSE) != D3D_OK)
  639.         return FALSE;
  640.     if (lpDev->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE) != D3D_OK)
  641.         return FALSE;
  642.     if (lpDev->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO) != D3D_OK)
  643. return FALSE;
  644.     if (lpDev->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE) != D3D_OK)
  645. return FALSE;
  646. lblCLEANUP: 
  647. // End Scene
  648. // Note:  This is complicated by the need to restore lost surfaces
  649.     hResult = lpDev->EndScene();
  650. if (hResult != D3D_OK) {
  651. while (hResult == DDERR_SURFACELOST) {
  652. // Restore surface
  653. while (hResult == DDERR_SURFACELOST) {
  654. hResult = lpd3dWindow->Restore();
  655. }
  656. // Try EndScene again
  657. hResult = lpDev->EndScene();
  658. }
  659. if (hResult != D3D_OK) {
  660. REPORTERR(hResult);
  661. return hResult;
  662. }
  663. }
  664. if (lpExtent) {
  665. hResult = lpDev->GetClipStatus(&status);
  666. if (hResult != D3D_OK) {
  667. REPORTERR(hResult);
  668. return hResult;
  669. }
  670. if (status.dwFlags & D3DCLIPSTATUS_EXTENTS2) {
  671. lpExtent->x1 = (long) floor((double)status.minx);
  672. lpExtent->x2 = (long) ceil((double)status.maxx);
  673. lpExtent->y1 = (long) floor((double)status.miny);
  674. lpExtent->y2 = (long) ceil((double)status.maxy);
  675. }
  676. }
  677. return hResult;
  678. } // End D3DScene::Render
  679.   
  680. /*
  681. **----------------------------------------------------------------------------
  682. ** Name:        D3DScene::Restore
  683. ** Purpose:     Restore any scene specific surfaces that might have been
  684. ** lost on a DDERR_LOSTSURFACE message
  685. **----------------------------------------------------------------------------
  686. */
  687. HRESULT D3DScene::Restore(void)
  688. {
  689. // Nothing to do for now
  690. // Success
  691. return D3D_OK;
  692. } // End D3DScene::Restore
  693.   
  694. /*
  695. **----------------------------------------------------------------------------
  696. ** Name:        D3DScene::AttachViewport
  697. ** Purpose:
  698. **----------------------------------------------------------------------------
  699. */
  700. HRESULT
  701. D3DScene::AttachViewport(void)
  702. {
  703. LPDIRECT3D2 lpD3D;
  704. LPDIRECT3DDEVICE2 lpDev;
  705. LPDIRECT3DVIEWPORT2    lpView;
  706. // Check Initialization
  707. if ((! lpd3dWindow) || (! lpd3dWindow->isValid())) {
  708. // Error,
  709. REPORTERR(DDERR_GENERIC);
  710. return DDERR_GENERIC;
  711. }
  712. lpD3D  = lpd3dWindow->lpD3D;
  713. lpDev  = lpd3dWindow->lpd3dDevice;
  714. lpView = lpd3dWindow->lpd3dViewport;
  715. if ((! lpD3D) || (! lpDev) || (! lpView)) {
  716. REPORTERR(DDERR_GENERIC);
  717. return DDERR_GENERIC;
  718. }
  719. // Create and set up the background material
  720. lpBackgroundMat = new Material(lpD3D, lpDev);
  721. lpBackgroundMat->SetDiffuse(D3DVECTOR(0.0f, 0.05f, 0.1f));
  722. lpBackgroundMat->SetAsBackground(lpView);
  723. // Create and set up the grid material, since we're using LVertices we want
  724. // to make sure that ramp mode can actually get the right colors so we set
  725. // the emissive value to the color we want and choose a small ramp size
  726. lpGridMat = new Material(lpD3D, lpDev);
  727. lpGridMat->SetEmissive(grid_color);
  728. lpGridMat->SetRampSize(2);
  729. // Create and set up the sphere material
  730. lpSphereMat = new Material(lpD3D, lpDev);
  731. lpSphereMat->SetDiffuse(D3DVECTOR(1.0f));
  732. // Create the sphere texture and attatch it to the material
  733. SphereTex.Load(lpDev, "DX5_logo");
  734. lpSphereMat->SetTextureHandle(SphereTex.GetHandle());
  735. // Create and set up the boid material
  736. // note that we'll just change the color for each boid we render
  737. lpBoidMat = new Material(lpD3D, lpDev);
  738. lpBoidMat->SetDiffuse(D3DVECTOR(1.0f));
  739. // set up transform matrices
  740. D3DVECTOR from(0.0f, 0.0f, -100.0f);
  741. D3DVECTOR at(0.0f, 0.0f, 0.0f);
  742. D3DVECTOR up(0.0f, 1.0f, 0.0f);
  743. view = ViewMatrix(from, at, up);
  744. proj = ProjectionMatrix(1.0f, 400.0f, pi/4.0f);
  745. world = IdentityMatrix();
  746. // create 2 lights
  747. D3DVECTOR color(1.0f, 1.0f, 1.0f);
  748. D3DVECTOR direction(-0.5f, -1.0f, -0.3f);
  749. lpLight1 = new DirectionalLight(lpD3D, color, Normalize(direction));
  750. if (lpLight1) {
  751. lpLight1->AddToViewport(lpView);
  752. }
  753. lpLight2 = new DirectionalLight(lpD3D, color/2.0f, -Normalize(direction));
  754. if (lpLight2) {
  755. lpLight2->AddToViewport(lpView);
  756. }
  757. // Success
  758.     return D3D_OK;
  759. } // End D3DScene::AttachViewport
  760. /*
  761. **-----------------------------------------------------------------------------
  762. **  Name:       D3DScene::DetachViewport
  763. **  Purpose: Cleanup Viewport
  764. **-----------------------------------------------------------------------------
  765. */
  766. HRESULT D3DScene::DetachViewport(void)
  767. {
  768. LPDIRECT3DVIEWPORT2 lpViewport = NULL;
  769. if (lpd3dWindow) {
  770. lpViewport = lpd3dWindow->GetViewport();
  771. }
  772. // Cleanup lights
  773. if (lpLight1) {
  774. if (lpViewport) {
  775. lpLight1->RemoveFromViewport(lpViewport);
  776. }
  777.     delete lpLight1;
  778. lpLight1 = NULL;
  779. }
  780. if (lpLight2) {
  781. if (lpViewport) {
  782. lpLight2->RemoveFromViewport(lpViewport);
  783. }
  784. delete lpLight2;
  785. lpLight2 = NULL;
  786. }
  787. // Cleanup Materials
  788. delete lpBackgroundMat;
  789. delete lpGridMat;
  790. delete lpSphereMat;
  791. delete lpBoidMat;
  792. lpBackgroundMat = NULL;
  793. lpGridMat = NULL;
  794. lpSphereMat = NULL;
  795. lpBoidMat = NULL;
  796. SphereTex.Release();
  797. // Success
  798. return D3D_OK;
  799. } // End D3DScene::DetachViewport
  800.   
  801. /*
  802. **----------------------------------------------------------------------------
  803. ** End of File
  804. **----------------------------------------------------------------------------
  805. */