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

DirextX编程

开发平台:

Visual C++

  1. // Fireworks.cpp : Defines the class behaviors for the application.
  2. #include "stdafx.h"
  3. #include "Fireworks.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 = 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 rnd() (((FLOAT)rand() - (FLOAT)rand()) / (2L * RAND_MAX))
  27. #define RND() (((FLOAT)rand()) / RAND_MAX)
  28. // Data structure for each particle
  29. struct Particle
  30. {
  31. D3DVECTOR dvPosition;
  32. D3DVECTOR dvLaunchVelocity;
  33. D3DVECTOR dvInitialPosition;
  34. D3DVECTOR dvInitialVelocity;
  35. FLOAT r, g, b;
  36. FLOAT fLifetime;
  37. FLOAT fMaturity;
  38. WORD wType;
  39. FLOAT fSize;
  40. };
  41. #define NUM_PARTICLES 100
  42. Particle g_Particle[NUM_PARTICLES]; // Array of particles
  43. D3DVERTEX g_Mesh[4]; // Vertices used to render particles
  44. D3DTLVERTEX g_Background[4]; // Vertices used to render the backdrop
  45. FLOAT g_fStartTimeKey = 0.0f; // Time reference for calculations
  46. // Initialize a particle
  47. Particle SetParticle(WORD  wType, FLOAT  fLifeTime, D3DVECTOR  vBasePosition,
  48. D3DVECTOR  vBaseVelocity)
  49. {
  50. Particle ret;
  51. ret.dvInitialVelocity = 15 * ::Normalize(D3DVECTOR(rnd(), rnd(), rnd()));
  52. ret.dvInitialVelocity += vBaseVelocity + D3DVECTOR(rnd(), rnd(), rnd());
  53. ret.dvInitialPosition = vBasePosition;
  54. ret.dvLaunchVelocity = vBaseVelocity;
  55. ret.r = 1.0f;
  56. ret.g = 1.0f;
  57. ret.b = 1.0f;
  58. ret.fLifetime = fLifeTime + fLifeTime * rnd() / 2;
  59. ret.fMaturity = 0.0f;
  60. ret.fSize = 0.2f;
  61. ret.wType = wType;
  62. return  ret;
  63. }
  64. CFireworksApp::CFireworksApp(void)
  65. {
  66. m_dwAppInitFlags &= ~CDirectXApp::DXAPPIF_DD;
  67. m_dwAppInitFlags |= CDirectXApp::DXAPPIF_D3DIM;
  68. SetFullScreen(g_bFullScreen);
  69. SetPackFileName(_T("Data"), _T("Data"));
  70. // Called during initial app startup, this function
  71. // performs all the permanent initialization.
  72. m_pD3DDevice = NULL;
  73. m_pD3DMaterial = NULL;
  74. // add your permanent init code here !
  75. m_pLakeTexture = NULL;
  76. m_pFireworkTexture = NULL;
  77. }
  78. // Called before the app exits, this function gives the app
  79. // the chance to cleanup after itself.
  80. CFireworksApp::~CFireworksApp()
  81. {
  82. // add your cleaup code here !
  83. }
  84. bool CFireworksApp::GetDXInitSettings(void)
  85. {
  86. if (m_pDirectSound != NULL)
  87. {
  88. if (m_pDirectSound->SelectDSDriver(0) == false)
  89. return  false;
  90. }
  91. if (m_pDirectMusic != NULL)
  92. {
  93. if (m_pDirectMusic->SelectDefaultDMusPort() == false)
  94. return  false;
  95. }
  96. if ((g_bUseVoodoo12 == false)
  97. || m_pDirectDraw->SelectDDDevice(0, 1) == false)
  98. {
  99. if (m_pDirectDraw->SelectDDDevice(0) == false)
  100. return  false;
  101. }
  102. if (g_bUseZBuffer)
  103. m_dwDDInitFlags |= CDDDevice::D3DIF_ZBUFFER;
  104. if (GetFirstDDDevice()->IsCanRenderWindowed() == false)
  105. {
  106. m_dwDDInitFlags &= ~CDDDevice::DDIF_WINDOWED;
  107. m_dwDDInitFlags &= ~CDDDevice::DDIF_NO_FLIP;
  108. }
  109. else
  110. {
  111. m_dwDDInitFlags |= CDDDevice::DDIF_NO_FLIP;
  112. }
  113. if (g_lpGuidD3DDevice == NULL)
  114. {
  115. if (GetFirstDDDevice()->SelectDefaultD3DDevice() == false)
  116. return  false;
  117. }
  118. else
  119. {
  120. if (GetFirstDDDevice()->SelectD3DDevice(g_lpGuidD3DDevice) == false)
  121. return  false;
  122. }
  123. if (GetFirstDDDevice()->SelectDisplayMode(
  124. IsFullScreen(), g_dwWidth, g_dwHeight, g_dwBPP) == false)
  125. return  false;
  126. return  true;
  127. }
  128. // Called during device intialization, this code checks the device
  129. // for some minimum set of capabilities, Initialize scene objects.
  130. bool CFireworksApp::InitDXObjects(void)
  131. {
  132. m_pD3DDevice = GetFirstD3DDevice();
  133. ASSERT(m_pD3DDevice != NULL);
  134. m_pD3DMaterial = m_pD3DDevice->GetD3DMaterial();
  135. // add your init code here !
  136. D3DPRIMCAPS const* pdpc = m_pD3DDevice->GetTriCaps();
  137. if ((pdpc->dwSrcBlendCaps & pdpc->dwDestBlendCaps & D3DBLEND_ONE) == 0)
  138. return  false;
  139. // Initialize the array of particles
  140. for (WORD  i = 0; i < NUM_PARTICLES; ++ i)
  141. g_Particle[i] = SetParticle(WORD(i % 3), 4.0f, D3DVECTOR(0, 0, 0),
  142. D3DVECTOR(0, 30, 0));
  143. // Initializes vertices used to render the particles
  144. D3DVECTOR dvNorm = D3DVECTOR(0.0f, 0.0f, 1.0f);
  145. g_Mesh[0] = D3DVERTEX(D3DVECTOR(-1.0f, -1.0f, 0.0f), dvNorm, 0.0f, 1.0f);
  146. g_Mesh[1] = D3DVERTEX(D3DVECTOR(-1.0f, 1.0f, 0.0f), dvNorm, 0.0f, 0.0f);
  147. g_Mesh[2] = D3DVERTEX(D3DVECTOR(1.0f, -1.0f, 0.0f), dvNorm, 1.0f, 1.0f);
  148. g_Mesh[3] = D3DVERTEX(D3DVECTOR(1.0f, 1.0f, 0.0f), dvNorm, 1.0f, 0.0f);
  149. // Initializes vertices used to render the background
  150. g_Background[0] = D3DTLVERTEX(D3DVECTOR(0, 0, 0.5), 0.5, D3DRGB(1, 1, 1), 0, 0, 1);
  151. g_Background[1] = D3DTLVERTEX(D3DVECTOR(0, 0, 0.5), 0.5, D3DRGB(1, 1, 1), 0, 0, 0);
  152. g_Background[2] = D3DTLVERTEX(D3DVECTOR(0, 0, 0.5), 0.5, D3DRGB(1, 1, 1), 0, 1, 1);
  153. g_Background[3] = D3DTLVERTEX(D3DVECTOR(0, 0, 0.5), 0.5, D3DRGB(1, 1, 1), 0, 1, 0);
  154. // Load in textures
  155. m_pLakeTexture = new  CD3DTexture;
  156. if (m_pLakeTexture->Create(m_pD3DDevice, _T("lake.bmp"), m_pPackFileManager, 0, 0) == false)
  157. {
  158. return  false;
  159. }
  160. m_pFireworkTexture = new  CD3DTexture;
  161. if (m_pFireworkTexture->Create(m_pD3DDevice, _T("firework.bmp"), m_pPackFileManager, 0, 0) == false)
  162. {
  163. return  false;
  164. }
  165. // Initialize scene objects
  166. // Set up the dimensions for the background image
  167. g_Background[0].sy = (FLOAT)m_pD3DDevice->GetHeight();
  168. g_Background[2].sy = (FLOAT)m_pD3DDevice->GetHeight();
  169. g_Background[2].sx = (FLOAT)m_pD3DDevice->GetWidth();
  170. g_Background[3].sx = (FLOAT)m_pD3DDevice->GetWidth();
  171.     
  172. // Set the transform matrices
  173. D3DVECTOR dvEyePt = D3DVECTOR(0.0f, 0.0f, -20.0f);
  174. D3DVECTOR dvLookatPt = D3DVECTOR(0.0f, 0.0f, 0.0f);
  175. D3DVECTOR dvUpVec = D3DVECTOR(0.0f, 0.0f, 1.0f);
  176. CD3DMatrix matView;
  177. matView.SetView(dvEyePt, dvLookatPt, dvUpVec);
  178. CD3DMatrix matProj;
  179. matProj.SetProjection(1.57f, 1.0f, 1.0f, 100.0f);
  180. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &matView);
  181. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj);
  182. // Set any appropiate state
  183. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xFFFFFFFF);
  184. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
  185. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE);
  186. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE);
  187. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE);
  188. m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  189. m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  190. m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_MODULATE);
  191. m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
  192. m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
  193. m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS,   D3DTADDRESS_CLAMP);
  194. return  true;
  195. }
  196. // Called when the app is exitting, or the device is being changed,
  197. // this function deletes any device dependant objects.
  198. bool CFireworksApp::DestroyDXObjects(void)
  199. {
  200. // add your destroy code here !
  201. if (m_pLakeTexture != NULL)
  202. {
  203. delete  m_pLakeTexture;
  204. m_pLakeTexture = NULL;
  205. }
  206. if (m_pFireworkTexture != NULL)
  207. {
  208. delete  m_pFireworkTexture;
  209. m_pFireworkTexture = NULL;
  210. }
  211. m_pD3DMaterial = NULL;
  212. m_pD3DDevice = NULL;
  213. return  CDirectXApp::DestroyDXObjects();
  214. }
  215. // Called once per frame, the call is the entry point for
  216. // animating the scene. This function sets up render states,
  217. // clears the viewport, and renders the scene.
  218. bool CFireworksApp::UpdateFrame(void)
  219. {
  220. // add your code here !
  221. // Get the relative time, in seconds
  222. FLOAT fTimeKey = ::timeGetTime() * 0.001f;
  223. D3DVECTOR a0 = D3DVECTOR( 0.0, -9.8f, 0.0f );
  224. FLOAT     t  = fTimeKey - g_fStartTimeKey;
  225. FLOAT     k  = 1.8f;
  226. DWORD dwNumOldParticles = 0L;
  227. // Store the particles positions
  228. for (DWORD  i = 0; i < NUM_PARTICLES; ++ i)
  229. {
  230. if (t < 0.0f) // Particle is in "launch" mode
  231. {
  232. D3DVECTOR v0 = g_Particle[i].dvLaunchVelocity;
  233. D3DVECTOR r0 = g_Particle[i].dvInitialPosition;
  234. g_Particle[i].dvPosition = r0 + v0*(t-RND()/10)/1.5f;
  235. else // Particle is in "explode" mode
  236. {
  237. D3DVECTOR v0 = g_Particle[i].dvInitialVelocity;
  238. D3DVECTOR r0 = g_Particle[i].dvInitialPosition;
  239. FLOAT fDamping = (1.0f - (FLOAT)exp(-k * t)) / (k * k);
  240. g_Particle[i].dvPosition = r0 + a0 * t / k + (k * v0 + a0) * fDamping;
  241. g_Particle[i].fMaturity = t / g_Particle[i].fLifetime;
  242. FLOAT st = g_Particle[i].fMaturity + 0.5f;
  243. g_Particle[i].r = (FLOAT)exp(-0.5f * st * st);
  244. g_Particle[i].g = (FLOAT)exp(-1.8f * st * st);
  245. g_Particle[i].b = (FLOAT)exp(-2.0f * st * st);
  246. g_Particle[i].fSize = (FLOAT)exp(-1.0f * st * st);
  247. if (g_Particle[i].fMaturity > 1.0f)
  248. ++ dwNumOldParticles;
  249. }
  250. }
  251. if (NUM_PARTICLES == dwNumOldParticles)
  252. {
  253. g_fStartTimeKey = fTimeKey + 1.0f;
  254. D3DVECTOR dvLaunchVelocity = D3DVECTOR(40.0f * rnd(), 30.0f, 0.0f);
  255. for (WORD  i = 0; i < NUM_PARTICLES; i ++)
  256. g_Particle[i] = SetParticle(WORD(i % 3), 4.0f, D3DVECTOR(0,0,0),
  257. dvLaunchVelocity);
  258. }
  259. // Begin the scene
  260. if (SUCCEEDED(m_pD3DDevice->BeginScene()))
  261. {
  262. // code !
  263. // Draw the background
  264. m_pLakeTexture->SetAsCurrent();
  265. m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
  266. D3DFVF_TLVERTEX, g_Background, 4, 0);
  267. // Render the particles
  268. RenderParticles();
  269. // End the scene.
  270. m_pD3DDevice->EndScene();
  271. }
  272. return  CDirectXApp::UpdateFrame();
  273. }
  274. // ---- add your functions ! ----
  275. // Draws the system of particles
  276. void CFireworksApp::RenderParticles(void)
  277. {
  278. // Turn on alpha blending for the particles
  279. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
  280. m_pFireworkTexture->SetAsCurrent();
  281. D3DCOLORVALUE dcvColor;
  282. dcvColor.dvA = 0.0f;
  283. // Do the particles
  284. for (DWORD  i = 0; i < NUM_PARTICLES; ++ i)
  285. {
  286. if (g_Particle[i].fMaturity > 1.0f)
  287. continue;
  288. // Set up the emissive color of the particle
  289. m_pD3DMaterial->SetColor(g_Particle[i].r, g_Particle[i].g, g_Particle[i].b, 0.0f, D3D_M_EMISSIVE);
  290. m_pD3DMaterial->Set();
  291. // Translate and scale the world matrix for each particle
  292. CD3DMatrix matWorld;
  293. matWorld.SetTranslate(g_Particle[i].dvPosition);
  294. matWorld._11 = g_Particle[i].fSize;
  295. matWorld._22 = g_Particle[i].fSize;
  296. // Set the new world transform and render the particle
  297. m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld);
  298. m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX,
  299. g_Mesh, 4, 0);
  300. }
  301. // Restore the material and states
  302. m_pD3DMaterial->SetColor(1.0f, 1.0f,  1.0f, 0.0f, D3D_M_EMISSIVE);
  303. m_pD3DMaterial->Set();
  304. m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
  305. }
  306. // ----
  307. #if _MSC_VER >= 1200 && _MSC_VER < 1400
  308. #ifdef _DEBUG
  309. #pragma comment(lib, "DXGuideD_VC6.lib")
  310. #else
  311. #pragma comment(lib, "DXGuide_VC6.lib")
  312. #endif // _DEBUG
  313. #endif // _MSC_VER
  314. #if _MSC_VER >= 1000 && _MSC_VER < 1200
  315. #ifdef _DEBUG
  316. #pragma comment(lib, "DXGuideD_VC5.lib")
  317. #else
  318. #pragma comment(lib, "DXGuide_VC5.lib")
  319. #endif // _DEBUG
  320. #endif // _MSC_VER
  321. BEGIN_MESSAGE_MAP(CFireworksApp, CDirectXApp)
  322. //{{AFX_MSG_MAP(CFireworksApp)
  323. //}}AFX_MSG_MAP
  324. END_MESSAGE_MAP()
  325. CFireworksApp theApp;