ShapeCloud.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. #include "gosFXHeaders.hpp"
  2. //==========================================================================//
  3. // File: gosFX_ShapeCloud.cpp //
  4. // Contents: Base gosFX::ShapeCloud Component //
  5. //---------------------------------------------------------------------------//
  6. // Copyright (C) Microsoft Corporation. All rights reserved. //
  7. //===========================================================================//
  8. //
  9. //############################################################################
  10. //######################## gosFX::ShapeCloud__Specification #############################
  11. //############################################################################
  12. //------------------------------------------------------------------------------
  13. //
  14. gosFX::ShapeCloud__Specification::ShapeCloud__Specification(
  15. Stuff::MemoryStream *stream,
  16. int gfx_version
  17. ):
  18. SpinningCloud__Specification(gosFX::ShapeCloudClassID, stream, gfx_version)
  19. {
  20. Check_Pointer(this);
  21. Verify(m_class == ShapeCloudClassID);
  22. Verify(gos_GetCurrentHeap() == Heap);
  23. m_particleClassSize = sizeof(gosFX::ShapeCloud::Particle);
  24. m_totalParticleSize = sizeof(gosFX::ShapeCloud::Particle);
  25. //
  26. //---------------
  27. // Load the shape
  28. //---------------
  29. //
  30. m_shape =
  31. MidLevelRenderer::MLRShape::Make(
  32. stream,
  33. MidLevelRenderer::ReadMLRVersion(stream)
  34. );
  35. Register_Object(m_shape);
  36. *stream >> m_radius;
  37. //
  38. //---------------------------------
  39. // Make sure everything is in order
  40. //---------------------------------
  41. //
  42. }
  43. //------------------------------------------------------------------------------
  44. //
  45. gosFX::ShapeCloud__Specification::ShapeCloud__Specification(
  46. MidLevelRenderer::MLRShape *shape
  47. ):
  48. SpinningCloud__Specification(gosFX::ShapeCloudClassID)
  49. {
  50. Check_Pointer(this);
  51. Verify(gos_GetCurrentHeap() == Heap);
  52. m_totalParticleSize = m_particleClassSize = sizeof(gosFX::ShapeCloud::Particle);
  53. m_shape = NULL;
  54. SetShape(shape);
  55. }
  56. //------------------------------------------------------------------------------
  57. //
  58. gosFX::ShapeCloud__Specification::~ShapeCloud__Specification()
  59. {
  60. Check_Object(this);
  61. if (m_shape)
  62. {
  63. Check_Object(m_shape);
  64. m_shape->DetachReference();
  65. }
  66. }
  67. //------------------------------------------------------------------------------
  68. //
  69. gosFX::ShapeCloud__Specification*
  70. gosFX::ShapeCloud__Specification::Make(
  71. Stuff::MemoryStream *stream,
  72. int gfx_version
  73. )
  74. {
  75. Check_Object(stream);
  76. gos_PushCurrentHeap(Heap);
  77. ShapeCloud__Specification *spec =
  78. new gosFX::ShapeCloud__Specification(stream, gfx_version);
  79. gos_PopCurrentHeap();
  80. return spec;
  81. }
  82. //------------------------------------------------------------------------------
  83. //
  84. void
  85. gosFX::ShapeCloud__Specification::Save(Stuff::MemoryStream *stream)
  86. {
  87. Check_Object(this);
  88. Check_Object(stream);
  89. SpinningCloud__Specification::Save(stream);
  90. MidLevelRenderer::WriteMLRVersion(stream);
  91. m_shape->Save(stream);
  92. *stream << m_radius;
  93. }
  94. //------------------------------------------------------------------------------
  95. //
  96. void
  97. gosFX::ShapeCloud__Specification::Copy(ShapeCloud__Specification *spec)
  98. {
  99. Check_Object(this);
  100. Check_Object(spec);
  101. SpinningCloud__Specification::Copy(spec);
  102. gos_PushCurrentHeap(Heap);
  103. m_radius = spec->m_radius;
  104. m_shape = spec->m_shape;
  105. gos_PopCurrentHeap();
  106. Check_Object(m_shape);
  107. m_shape->AttachReference();
  108. }
  109. //------------------------------------------------------------------------------
  110. //
  111. void
  112. gosFX::ShapeCloud__Specification::SetShape(MidLevelRenderer::MLRShape *shape)
  113. {
  114. Check_Object(this);
  115. //
  116. //------------------------------------
  117. // Detach the old shape if it is there
  118. //------------------------------------
  119. //
  120. if (m_shape)
  121. {
  122. Check_Object(m_shape);
  123. m_shape->DetachReference();
  124. }
  125. //
  126. //------------------------------------
  127. // Attach the new shape if it is there
  128. //------------------------------------
  129. //
  130. if (shape)
  131. {
  132. Check_Object(shape);
  133. m_shape = shape;
  134. m_shape->AttachReference();
  135. //
  136. //-----------------------------------------------------------------
  137. // Get the radius of the bounding sphere. This will be the largest
  138. // distance any point is from the origin
  139. //-----------------------------------------------------------------
  140. //
  141. m_radius = 0.0f;
  142. int count = m_shape->GetNum();
  143. for (int i=0; i<count; ++i)
  144. {
  145. MidLevelRenderer::MLRPrimitiveBase *primitive = m_shape->Find(i);
  146. Check_Object(primitive);
  147. Stuff::Point3D *points;
  148. int vertex_count;
  149. primitive->GetCoordData(&points, &vertex_count);
  150. for (int v=0; v<vertex_count; ++v)
  151. {
  152. Stuff::Scalar len = points[v].GetLengthSquared();
  153. if (len > m_radius)
  154. m_radius = len;
  155. }
  156. }
  157. m_radius = Stuff::Sqrt(m_radius);
  158. }
  159. }
  160. //############################################################################
  161. //############################## gosFX::ShapeCloud ################################
  162. //############################################################################
  163. gosFX::ShapeCloud::ClassData*
  164. gosFX::ShapeCloud::DefaultData = NULL;
  165. //------------------------------------------------------------------------------
  166. //
  167. void
  168. gosFX::ShapeCloud::InitializeClass()
  169. {
  170. Verify(!DefaultData);
  171. Verify(gos_GetCurrentHeap() == Heap);
  172. DefaultData =
  173. new ClassData(
  174. ShapeCloudClassID,
  175. "gosFX::ShapeCloud",
  176. SpinningCloud::DefaultData,
  177. (Effect::Factory)&Make,
  178. (Specification::Factory)&Specification::Make
  179. );
  180. Register_Object(DefaultData);
  181. }
  182. //------------------------------------------------------------------------------
  183. //
  184. void
  185. gosFX::ShapeCloud::TerminateClass()
  186. {
  187. Unregister_Object(DefaultData);
  188. delete DefaultData;
  189. DefaultData = NULL;
  190. }
  191. //------------------------------------------------------------------------------
  192. //
  193. gosFX::ShapeCloud::ShapeCloud(
  194. Specification *spec,
  195. unsigned flags
  196. ):
  197. SpinningCloud(DefaultData, spec, flags)
  198. {
  199. Verify(gos_GetCurrentHeap() == Heap);
  200. }
  201. //------------------------------------------------------------------------------
  202. //
  203. gosFX::ShapeCloud*
  204. gosFX::ShapeCloud::Make(
  205. Specification *spec,
  206. unsigned flags
  207. )
  208. {
  209. Check_Object(spec);
  210. gos_PushCurrentHeap(Heap);
  211. ShapeCloud *cloud = new gosFX::ShapeCloud(spec, flags);
  212. gos_PopCurrentHeap();
  213. return cloud;
  214. }
  215. //------------------------------------------------------------------------------
  216. //
  217. void
  218. gosFX::ShapeCloud::CreateNewParticle(
  219. unsigned index,
  220. Stuff::Point3D *translation
  221. )
  222. {
  223. Check_Object(this);
  224. //
  225. //-------------------------------------------------------------------
  226. // Let our parent do creation, then turn on the particle in the cloud
  227. //-------------------------------------------------------------------
  228. //
  229. SpinningCloud::CreateNewParticle(index, translation);
  230. Specification *spec = GetSpecification();
  231. Check_Object(spec);
  232. Particle *particle = GetParticle(index);
  233. Check_Object(particle);
  234. particle->m_radius = spec->m_radius;
  235. }
  236. //------------------------------------------------------------------------------
  237. //
  238. bool
  239. gosFX::ShapeCloud::AnimateParticle(
  240. unsigned index,
  241. const Stuff::LinearMatrix4D *world_to_new_local,
  242. Stuff::Time till
  243. )
  244. {
  245. Check_Object(this);
  246. //
  247. //-----------------------------------------
  248. // Animate the parent then get our pointers
  249. //-----------------------------------------
  250. //
  251. if (!SpinningCloud::AnimateParticle(index, world_to_new_local, till))
  252. return false;
  253. Set_Statistic(Shape_Count, Shape_Count+1);
  254. Specification *spec = GetSpecification();
  255. Check_Object(spec);
  256. Particle *particle = GetParticle(index);
  257. Check_Object(particle);
  258. Stuff::Scalar seed = particle->m_seed;
  259. Stuff::Scalar age = particle->m_age;
  260. //
  261. //------------------
  262. // Animate the color
  263. //------------------
  264. //
  265. particle->m_color.red = spec->m_pRed.ComputeValue(age, seed);
  266. particle->m_color.green = spec->m_pGreen.ComputeValue(age, seed);
  267. particle->m_color.blue = spec->m_pBlue.ComputeValue(age, seed);
  268. particle->m_color.alpha = spec->m_pAlpha.ComputeValue(age, seed);
  269. return true;
  270. }
  271. //------------------------------------------------------------------------------
  272. //
  273. void gosFX::ShapeCloud::Draw(DrawInfo *info)
  274. {
  275. Check_Object(this);
  276. Check_Object(info);
  277. Check_Object(info->m_parentToWorld);
  278. //
  279. //----------------------------
  280. // Set up the common draw info
  281. //----------------------------
  282. //
  283. if (m_activeParticleCount)
  284. {
  285. MidLevelRenderer::DrawScalableShapeInformation dinfo;
  286. MidLevelRenderer::MLRShape *shape = GetSpecification()->m_shape;
  287. dinfo.clippingFlags.SetClippingState(0x3f);
  288. dinfo.worldToShape = NULL;
  289. Specification *spec = GetSpecification();
  290. Check_Object(spec);
  291. dinfo.state.Combine(info->m_state, spec->m_state);
  292. dinfo.activeLights = NULL;
  293. dinfo.nrOfActiveLights = 0;
  294. dinfo.shape = shape;
  295. Stuff::LinearMatrix4D local_to_world;
  296. local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
  297. //
  298. //--------------------------------------------------------------
  299. // Check the orientation mode. The first case is XY orientation
  300. //--------------------------------------------------------------
  301. //
  302. unsigned i;
  303. if (spec->m_alignZUsingX)
  304. {
  305. if (spec->m_alignZUsingY)
  306. {
  307. //
  308. //-----------------------------------------
  309. // Get the camera location into local space
  310. //-----------------------------------------
  311. //
  312. Stuff::Point3D
  313. camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
  314. Stuff::Point3D camera_in_cloud;
  315. camera_in_cloud.MultiplyByInverse(
  316. camera_in_world,
  317. local_to_world
  318. );
  319. for (unsigned i = 0; i < m_activeParticleCount; i++)
  320. {
  321. Particle *particle = GetParticle(i);
  322. Check_Object(particle);
  323. //
  324. //-----------------------------------------------------------------
  325. // If the particle is still alive, concatenate into world space and
  326. // issue the draw command
  327. //-----------------------------------------------------------------
  328. //
  329. if (particle->m_age < 1.0f)
  330. {
  331. Stuff::Vector3D direction_in_cloud;
  332. direction_in_cloud.Subtract(
  333. camera_in_cloud,
  334. particle->m_localTranslation
  335. );
  336. Stuff::LinearMatrix4D shape_to_cloud;
  337. shape_to_cloud.BuildRotation(particle->m_localRotation);
  338. shape_to_cloud.AlignLocalAxisToWorldVector(
  339. direction_in_cloud,
  340. Stuff::Z_Axis,
  341. Stuff::Y_Axis,
  342. Stuff::X_Axis
  343. );
  344. shape_to_cloud.BuildTranslation(particle->m_localTranslation);
  345. Stuff::LinearMatrix4D shape_to_world;
  346. shape_to_world.Multiply(
  347. shape_to_cloud,
  348. local_to_world
  349. );
  350. dinfo.shapeToWorld = &shape_to_world;
  351. Stuff::Vector3D
  352. scale(
  353. particle->m_scale,
  354. particle->m_scale,
  355. particle->m_scale
  356. );
  357. dinfo.scaling = &scale;
  358. dinfo.paintMe = &particle->m_color;
  359. info->m_clipper->DrawScalableShape(&dinfo);
  360. }
  361. }
  362. }
  363. //
  364. //-----------------------
  365. // Handle X-only rotation
  366. //-----------------------
  367. //
  368. else
  369. {
  370. //
  371. //-----------------------------------------
  372. // Get the camera location into local space
  373. //-----------------------------------------
  374. //
  375. Stuff::Point3D
  376. camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
  377. Stuff::Point3D camera_in_cloud;
  378. camera_in_cloud.MultiplyByInverse(
  379. camera_in_world,
  380. local_to_world
  381. );
  382. for (unsigned i = 0; i < m_activeParticleCount; i++)
  383. {
  384. Particle *particle = GetParticle(i);
  385. Check_Object(particle);
  386. //
  387. //-----------------------------------------------------------------
  388. // If the particle is still alive, concatenate into world space and
  389. // issue the draw command
  390. //-----------------------------------------------------------------
  391. //
  392. if (particle->m_age < 1.0f)
  393. {
  394. Stuff::Vector3D direction_in_cloud;
  395. direction_in_cloud.Subtract(
  396. camera_in_cloud,
  397. particle->m_localTranslation
  398. );
  399. Stuff::LinearMatrix4D shape_to_cloud;
  400. shape_to_cloud.BuildRotation(particle->m_localRotation);
  401. shape_to_cloud.AlignLocalAxisToWorldVector(
  402. direction_in_cloud,
  403. Stuff::Z_Axis,
  404. Stuff::X_Axis,
  405. -1
  406. );
  407. shape_to_cloud.BuildTranslation(particle->m_localTranslation);
  408. Stuff::LinearMatrix4D shape_to_world;
  409. shape_to_world.Multiply(
  410. shape_to_cloud,
  411. local_to_world
  412. );
  413. dinfo.shapeToWorld = &shape_to_world;
  414. Stuff::Vector3D
  415. scale(
  416. particle->m_scale,
  417. particle->m_scale,
  418. particle->m_scale
  419. );
  420. dinfo.scaling = &scale;
  421. dinfo.paintMe = &particle->m_color;
  422. info->m_clipper->DrawScalableShape(&dinfo);
  423. }
  424. }
  425. }
  426. }
  427. //
  428. //-------------------------------------------------------
  429. // Each matrix needs to be aligned to the camera around Y
  430. //-------------------------------------------------------
  431. //
  432. else if (spec->m_alignZUsingY)
  433. {
  434. //
  435. //-----------------------------------------
  436. // Get the camera location into local space
  437. //-----------------------------------------
  438. //
  439. Stuff::Point3D
  440. camera_in_world(info->m_clipper->GetCameraToWorldMatrix());
  441. Stuff::Point3D camera_in_cloud;
  442. camera_in_cloud.MultiplyByInverse(
  443. camera_in_world,
  444. local_to_world
  445. );
  446. for (unsigned i = 0; i < m_activeParticleCount; i++)
  447. {
  448. Particle *particle = GetParticle(i);
  449. Check_Object(particle);
  450. //
  451. //-----------------------------------------------------------------
  452. // If the particle is still alive, concatenate into world space and
  453. // issue the draw command
  454. //-----------------------------------------------------------------
  455. //
  456. if (particle->m_age < 1.0f)
  457. {
  458. Stuff::Vector3D direction_in_cloud;
  459. direction_in_cloud.Subtract(
  460. camera_in_cloud,
  461. particle->m_localTranslation
  462. );
  463. Stuff::LinearMatrix4D shape_to_cloud;
  464. shape_to_cloud.BuildRotation(particle->m_localRotation);
  465. shape_to_cloud.AlignLocalAxisToWorldVector(
  466. direction_in_cloud,
  467. Stuff::Z_Axis,
  468. Stuff::Y_Axis,
  469. -1
  470. );
  471. shape_to_cloud.BuildTranslation(particle->m_localTranslation);
  472. Stuff::LinearMatrix4D shape_to_world;
  473. shape_to_world.Multiply(
  474. shape_to_cloud,
  475. local_to_world
  476. );
  477. dinfo.shapeToWorld = &shape_to_world;
  478. Stuff::Vector3D
  479. scale(
  480. particle->m_scale,
  481. particle->m_scale,
  482. particle->m_scale
  483. );
  484. dinfo.scaling = &scale;
  485. dinfo.paintMe = &particle->m_color;
  486. info->m_clipper->DrawScalableShape(&dinfo);
  487. }
  488. }
  489. }
  490. //
  491. //---------------------------------------------------------------
  492. // No alignment is necessary, so just multiply out all the active
  493. // particles
  494. //---------------------------------------------------------------
  495. //
  496. else
  497. {
  498. for (i=0; i < m_activeParticleCount; i++)
  499. {
  500. Particle *particle = GetParticle(i);
  501. Check_Object(particle);
  502. //
  503. //-----------------------------------------------------------------
  504. // If the particle is still alive, concatenate into world space and
  505. // issue the draw command
  506. //-----------------------------------------------------------------
  507. //
  508. if (particle->m_age < 1.0f)
  509. {
  510. Stuff::LinearMatrix4D shape_to_cloud;
  511. shape_to_cloud.BuildTranslation(particle->m_localTranslation);
  512. shape_to_cloud.BuildRotation(particle->m_localRotation);
  513. Stuff::LinearMatrix4D shape_to_world;
  514. shape_to_world.Multiply(
  515. shape_to_cloud,
  516. local_to_world
  517. );
  518. dinfo.shapeToWorld = &shape_to_world;
  519. Stuff::Vector3D
  520. scale(
  521. particle->m_scale,
  522. particle->m_scale,
  523. particle->m_scale
  524. );
  525. dinfo.scaling = &scale;
  526. dinfo.paintMe = &particle->m_color;
  527. info->m_clipper->DrawScalableShape(&dinfo);
  528. }
  529. }
  530. }
  531. }
  532. //
  533. //----------------------------
  534. // Let our parent do its thing
  535. //----------------------------
  536. //
  537. SpinningCloud::Draw(info);
  538. }
  539. //------------------------------------------------------------------------------
  540. //
  541. void
  542. gosFX::ShapeCloud::TestInstance() const
  543. {
  544. Verify(IsDerivedFrom(DefaultData));
  545. }