DebrisCloud.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. #include "gosFXHeaders.hpp"
  2. //==========================================================================//
  3. // File: gosFX_DebrisCloud.cpp //
  4. // Contents: Base gosFX::DebrisCloud Component //
  5. //---------------------------------------------------------------------------//
  6. // Copyright (C) Microsoft Corporation. All rights reserved. //
  7. //===========================================================================//
  8. //
  9. //############################################################################
  10. //######################## gosFX::DebrisCloud__Specification #############################
  11. //############################################################################
  12. //------------------------------------------------------------------------------
  13. //
  14. gosFX::DebrisCloud__Specification::DebrisCloud__Specification(
  15. Stuff::MemoryStream *stream,
  16. int gfx_version
  17. ):
  18. Effect__Specification(gosFX::DebrisCloudClassID, stream, gfx_version)
  19. {
  20. Check_Pointer(this);
  21. Verify(m_class == DebrisCloudClassID);
  22. Verify(gos_GetCurrentHeap() == Heap);
  23. m_minimumDeviation.Load(stream, gfx_version); // ConstantCurve
  24. m_maximumDeviation.Load(stream, gfx_version); // SplineCurve
  25. m_startingSpeed.Load(stream, gfx_version); // SeededCurveOf<ComplexCurve, ComplexCurve,Curve::e_ComplexComplexType>
  26. m_pLifeSpan.Load(stream, gfx_version); // SeededCurveOf<ComplexCurve, SplineCurve,Curve::e_ComplexSplineType>
  27. m_pEtherVelocityY.Load(stream, gfx_version); // SeededCurveOf<ConstantCurve, LinearCurve,Curve::e_ConstantLinearType>
  28. m_pAccelerationY.Load(stream, gfx_version); // SeededCurveOf<SplineCurve, LinearCurve,Curve::e_SplineLinearType>
  29. m_pDrag.Load(stream, gfx_version); // SeededCurveOf<ComplexCurve, ComplexCurve,Curve::e_ComplexComplexType>
  30. m_pAlpha.Load(stream, gfx_version); // SeededCurveOf<ComplexCurve, LinearCurve,Curve::e_ComplexLinearType>
  31. m_pSpin.Load(stream, gfx_version); // SeededCurveOf<ConstantCurve, LinearCurve,Curve::e_ConstantLinearType>
  32. *stream >> centerOfForce; // Stuff::Point3D
  33. LoadGeometry(stream);
  34. }
  35. //------------------------------------------------------------------------------
  36. //
  37. gosFX::DebrisCloud__Specification::DebrisCloud__Specification():
  38. Effect__Specification(gosFX::DebrisCloudClassID)
  39. {
  40. Check_Pointer(this);
  41. Verify(gos_GetCurrentHeap() == Heap);
  42. debrisPieces.SetLength(0);
  43. debrisPositions.SetLength(0);
  44. debrisSpheres.SetLength(0);
  45. debrisSeed.SetLength(0);
  46. }
  47. //------------------------------------------------------------------------------
  48. //
  49. gosFX::DebrisCloud__Specification::~DebrisCloud__Specification()
  50. {
  51. Check_Object(this);
  52. int i, nrOfParticles = debrisPieces.GetLength();
  53. for(i=0;i<nrOfParticles;i++)
  54. {
  55. Check_Object(debrisPieces[i]);
  56. debrisPieces[i]->DetachReference();
  57. }
  58. debrisPieces.SetLength(0);
  59. debrisPositions.SetLength(0);
  60. debrisSpheres.SetLength(0);
  61. debrisSeed.SetLength(0);
  62. }
  63. //------------------------------------------------------------------------------
  64. //
  65. gosFX::DebrisCloud__Specification*
  66. gosFX::DebrisCloud__Specification::Make(
  67. Stuff::MemoryStream *stream,
  68. int gfx_version
  69. )
  70. {
  71. Check_Object(stream);
  72. gos_PushCurrentHeap(Heap);
  73. DebrisCloud__Specification *spec =
  74. new gosFX::DebrisCloud__Specification(stream, gfx_version);
  75. gos_PopCurrentHeap();
  76. return spec;
  77. }
  78. //------------------------------------------------------------------------------
  79. //
  80. void
  81. gosFX::DebrisCloud__Specification::Save(Stuff::MemoryStream *stream)
  82. {
  83. Check_Object(this);
  84. Check_Object(stream);
  85. Effect__Specification::Save(stream);
  86. m_minimumDeviation.Save(stream); // ConstantCurve
  87. m_maximumDeviation.Save(stream); // SplineCurve
  88. m_startingSpeed.Save(stream); // SeededCurveOf<ComplexCurve, ComplexCurve,Curve::e_ComplexComplexType>
  89. m_pLifeSpan.Save(stream); // SeededCurveOf<ComplexCurve, SplineCurve,Curve::e_ComplexSplineType>
  90. m_pEtherVelocityY.Save(stream); // SeededCurveOf<ConstantCurve, LinearCurve,Curve::e_ConstantLinearType>
  91. m_pAccelerationY.Save(stream); // SeededCurveOf<SplineCurve, LinearCurve,Curve::e_SplineLinearType>
  92. m_pDrag.Save(stream); // SeededCurveOf<ComplexCurve, ComplexCurve,Curve::e_ComplexComplexType>
  93. m_pAlpha.Save(stream); // SeededCurveOf<ComplexCurve, LinearCurve,Curve::e_ComplexLinearType>
  94. m_pSpin.Save(stream); // SeededCurveOf<ConstantCurve, LinearCurve,Curve::e_ConstantLinearType>
  95. *stream << centerOfForce; // Stuff::Point3D
  96. MidLevelRenderer::WriteMLRVersion(stream);
  97. int i, nrOfParticles = debrisPieces.GetLength();
  98. *stream << nrOfParticles;
  99. for(i=0;i<nrOfParticles;i++)
  100. {
  101. *stream << debrisPositions[i];
  102. *stream << debrisSpheres[i].center;
  103. *stream << debrisSpheres[i].radius;
  104. Check_Object(debrisPieces[i]);
  105. debrisPieces[i]->Save(stream);
  106. }
  107. }
  108. //------------------------------------------------------------------------------
  109. //
  110. void
  111. gosFX::DebrisCloud__Specification::Copy(DebrisCloud__Specification *spec)
  112. {
  113. Check_Object(this);
  114. Check_Object(spec);
  115. Effect__Specification::Copy(spec);
  116. gos_PushCurrentHeap(Heap);
  117. m_minimumDeviation = spec->m_minimumDeviation; // ConstantCurve
  118. m_maximumDeviation = spec->m_maximumDeviation; // SplineCurve
  119. m_startingSpeed = spec->m_startingSpeed; // SeededCurveOf<ComplexCurve, ComplexCurve,Curve::e_ComplexComplexType>
  120. m_pLifeSpan = spec->m_pLifeSpan; // SeededCurveOf<ComplexCurve, SplineCurve,Curve::e_ComplexSplineType>
  121. m_pEtherVelocityY = spec->m_pEtherVelocityY; // SeededCurveOf<ConstantCurve, LinearCurve,Curve::e_ConstantLinearType>
  122. m_pAccelerationY = spec->m_pAccelerationY; // SeededCurveOf<SplineCurve, LinearCurve,Curve::e_SplineLinearType>
  123. m_pDrag = spec->m_pDrag; // SeededCurveOf<ComplexCurve, ComplexCurve,Curve::e_ComplexComplexType>
  124. m_pAlpha = spec->m_pAlpha; // SeededCurveOf<ComplexCurve, LinearCurve,Curve::e_ComplexLinearType>
  125. m_pSpin = spec->m_pSpin; // SeededCurveOf<ConstantCurve, LinearCurve,Curve::e_ConstantLinearType>
  126. centerOfForce = spec->centerOfForce; // Stuff::Point3D
  127. int i, nrOfParticles = spec->debrisPieces.GetLength();
  128. debrisPieces.SetLength(nrOfParticles);
  129. debrisPositions.SetLength(nrOfParticles);
  130. debrisSpheres.SetLength(nrOfParticles);
  131. debrisSeed.SetLength(nrOfParticles);
  132. for(i=0;i<nrOfParticles;i++)
  133. {
  134. debrisPositions[i] = spec->debrisPositions[i];
  135. debrisSpheres[i] = spec->debrisSpheres[i];
  136. debrisPieces[i] = spec->debrisPieces[i];
  137. Check_Object(debrisPieces[i]);
  138. debrisPieces[i]->AttachReference();
  139. debrisSeed[i] = spec->debrisSeed[i];
  140. }
  141. gos_PopCurrentHeap();
  142. }
  143. //------------------------------------------------------------------------------
  144. //
  145. void
  146. gosFX::DebrisCloud__Specification::LoadGeometry(Stuff::MemoryStream *stream)
  147. {
  148. int i, mlrVersion, nrOfParticles;
  149. mlrVersion = MidLevelRenderer::ReadMLRVersion(stream);
  150. *stream >> nrOfParticles;
  151. debrisPieces.SetLength(nrOfParticles);
  152. debrisPositions.SetLength(nrOfParticles);
  153. debrisSpheres.SetLength(nrOfParticles);
  154. debrisSeed.SetLength(nrOfParticles);
  155. Stuff::Scalar minRadius = 100000000000.0f, maxRadius = 0.0f;
  156. for(i=0;i<nrOfParticles;i++)
  157. {
  158. *stream >> debrisPositions[i];
  159. *stream >> debrisSpheres[i].center;
  160. *stream >> debrisSpheres[i].radius;
  161. if(debrisSpheres[i].radius < minRadius)
  162. {
  163. minRadius = debrisSpheres[i].radius;
  164. }
  165. if(debrisSpheres[i].radius > maxRadius)
  166. {
  167. maxRadius = debrisSpheres[i].radius;
  168. }
  169. //
  170. //---------------
  171. // Load the shape
  172. //---------------
  173. //
  174. debrisPieces[i] =
  175. MidLevelRenderer::MLRShape::Make(
  176. stream,
  177. mlrVersion
  178. );
  179. Register_Object(debrisPieces[i]);
  180. }
  181. Verify(maxRadius > minRadius);
  182. for(i=0;i<nrOfParticles;i++)
  183. {
  184. debrisSeed[i] = (debrisSpheres[i].radius-minRadius)/(maxRadius-minRadius);
  185. }
  186. }
  187. //------------------------------------------------------------------------------
  188. //
  189. void
  190. gosFX::DebrisCloud__Specification::BuildDefaults()
  191. {
  192. Check_Object(this);
  193. Effect__Specification::BuildDefaults();
  194. centerOfForce = Stuff::Point3D(0.0f, 00.0f, 0.0f);
  195. m_lifeSpan.SetCurve(20.0f);
  196. m_minimumDeviation.SetCurve(0.0f);
  197. m_maximumDeviation.SetCurve(Stuff::Pi_Over_6);
  198. m_startingSpeed.m_ageCurve.SetCurve(1.0f);
  199. m_startingSpeed.m_seeded = true;
  200. m_startingSpeed.m_seedCurve.SetCurve(1.0f, 3.0f);
  201. m_pEtherVelocityY.m_ageCurve.SetCurve(0.0f);
  202. m_pEtherVelocityY.m_seeded = false;
  203. m_pEtherVelocityY.m_seedCurve.SetCurve(1.0f);
  204. m_pAccelerationY.m_ageCurve.SetCurve(-9.8f);
  205. m_pAccelerationY.m_seeded = false;
  206. m_pAccelerationY.m_seedCurve.SetCurve(1.0f);
  207. m_pDrag.m_ageCurve.SetCurve(0.3f);
  208. m_pDrag.m_seeded = false;
  209. m_pDrag.m_seedCurve.SetCurve(1.0f);
  210. m_pAlpha.m_ageCurve.SetCurve(1.0f);
  211. m_pAlpha.m_seeded = false;
  212. m_pAlpha.m_seedCurve.SetCurve(1.0f);
  213. m_pSpin.m_ageCurve.SetCurve(Stuff::Pi_Over_2);
  214. m_pSpin.m_seeded = true;
  215. m_pSpin.m_seedCurve.SetCurve(-1.0f, 1.0f);
  216. m_pLifeSpan.m_ageCurve.SetCurve(20.0f);
  217. m_pLifeSpan.m_seeded = false;
  218. m_pLifeSpan.m_seedCurve.SetCurve(1.0f);
  219. }
  220. //------------------------------------------------------------------------------
  221. //
  222. bool
  223. gosFX::DebrisCloud__Specification::IsDataValid(bool fix_data)
  224. {
  225. Check_Object(this);
  226. return Effect__Specification::IsDataValid(fix_data);
  227. /*
  228. centerOfForce = Stuff::Point3D(0.0f, 00.0f, 0.0f);
  229. m_lifeSpan.SetCurve(20.0f);
  230. m_minimumDeviation.SetCurve(0.0f);
  231. m_maximumDeviation.SetCurve(Stuff::Pi_Over_6);
  232. m_startingSpeed.m_ageCurve.SetCurve(1.0f);
  233. m_startingSpeed.m_seeded = true;
  234. m_startingSpeed.m_seedCurve.SetCurve(1.0f, 3.0f);
  235. m_pEtherVelocityY.m_ageCurve.SetCurve(0.0f);
  236. m_pEtherVelocityY.m_seeded = false;
  237. m_pEtherVelocityY.m_seedCurve.SetCurve(1.0f);
  238. m_pAccelerationY.m_ageCurve.SetCurve(-9.8f);
  239. m_pAccelerationY.m_seeded = false;
  240. m_pAccelerationY.m_seedCurve.SetCurve(1.0f);
  241. m_pDrag.m_ageCurve.SetCurve(0.3f);
  242. m_pDrag.m_seeded = false;
  243. m_pDrag.m_seedCurve.SetCurve(1.0f);
  244. m_pAlpha.m_ageCurve.SetCurve(1.0f);
  245. m_pAlpha.m_seeded = false;
  246. m_pAlpha.m_seedCurve.SetCurve(1.0f);
  247. m_pSpin.m_ageCurve.SetCurve(Stuff::Pi_Over_2);
  248. m_pSpin.m_seeded = true;
  249. m_pSpin.m_seedCurve.SetCurve(-1.0f, 1.0f);
  250. m_pLifeSpan.m_ageCurve.SetCurve(20.0f);
  251. m_pLifeSpan.m_seeded = false;
  252. m_pLifeSpan.m_seedCurve.SetCurve(1.0f);
  253. */
  254. }
  255. //############################################################################
  256. //########################## gosFX::DebrisCloud ############################
  257. //############################################################################
  258. gosFX::DebrisCloud::ClassData*
  259. gosFX::DebrisCloud::DefaultData = NULL;
  260. //------------------------------------------------------------------------------
  261. //
  262. void
  263. gosFX::DebrisCloud::InitializeClass()
  264. {
  265. Verify(!DefaultData);
  266. Verify(gos_GetCurrentHeap() == Heap);
  267. DefaultData =
  268. new ClassData(
  269. DebrisCloudClassID,
  270. "gosFX::DebrisCloud",
  271. EffectCloud::DefaultData,
  272. (Effect::Factory)&Make,
  273. (Specification::Factory)&Specification::Make
  274. );
  275. Register_Object(DefaultData);
  276. }
  277. //------------------------------------------------------------------------------
  278. //
  279. void
  280. gosFX::DebrisCloud::TerminateClass()
  281. {
  282. Unregister_Object(DefaultData);
  283. delete DefaultData;
  284. DefaultData = NULL;
  285. }
  286. //------------------------------------------------------------------------------
  287. //
  288. gosFX::DebrisCloud::DebrisCloud(
  289. Specification *spec,
  290. unsigned flags
  291. ):
  292. Effect(DefaultData, spec, flags)
  293. {
  294. Verify(gos_GetCurrentHeap() == Heap);
  295. debrisPieces.SetLength(spec->debrisPieces.GetLength());
  296. }
  297. //------------------------------------------------------------------------------
  298. //
  299. gosFX::DebrisCloud*
  300. gosFX::DebrisCloud::Make(
  301. Specification *spec,
  302. unsigned flags
  303. )
  304. {
  305. Check_Object(spec);
  306. gos_PushCurrentHeap(Heap);
  307. DebrisCloud *cloud = new gosFX::DebrisCloud(spec, flags);
  308. gos_PopCurrentHeap();
  309. return cloud;
  310. }
  311. //------------------------------------------------------------------------------
  312. //
  313. void
  314. gosFX::DebrisCloud::Start(struct gosFX::Effect::ExecuteInfo *info)
  315. {
  316. Check_Object(this);
  317. Check_Pointer(info);
  318. //
  319. //--------------------------------------------------------------------------
  320. // Let effect initialize, then figure out how many particles we want to make
  321. //--------------------------------------------------------------------------
  322. //
  323. Effect::Start(info);
  324. Specification *spec = GetSpecification();
  325. Check_Object(spec);
  326. Verify(debrisPieces.GetLength() == spec->debrisPieces.GetLength());
  327. int i, numOfParticles = debrisPieces.GetLength();
  328. for(i=0;i<numOfParticles;i++)
  329. {
  330. Particle *particle = &debrisPieces[i];
  331. particle->m_localToParent = Stuff::LinearMatrix4D::Identity;
  332. particle->m_localToParent.BuildTranslation(spec->debrisPositions[i]);
  333. particle->m_age = 0.0f;
  334. particle->m_seed = spec->debrisSeed[i];
  335. Stuff::Scalar lifetime =
  336. spec->m_pLifeSpan.ComputeValue(0.0f, particle->m_seed);
  337. Min_Clamp(lifetime, 0.0333333f);
  338. particle->m_ageRate = 1.0f / lifetime;
  339. Stuff::Vector3D v;
  340. v.Subtract(spec->debrisPositions[i], spec->centerOfForce);
  341. // v.y = 0.0f;
  342. Stuff::Scalar lerpFactor =
  343. Stuff::Lerp(
  344. spec->m_minimumDeviation.ComputeValue(0.0f, particle->m_seed),
  345. spec->m_maximumDeviation.ComputeValue(0.0f, particle->m_seed),
  346. Stuff::Random::GetFraction()
  347. );
  348. particle->m_linearVelocity.Lerp(Stuff::Vector3D::Up, v, lerpFactor);
  349. particle->m_linearVelocity.Normalize(particle->m_linearVelocity);
  350. particle->m_linearVelocity *= spec->m_startingSpeed.ComputeValue(0.0f, particle->m_seed);
  351. Stuff::Scalar temp = spec->m_pSpin.ComputeValue(0.0f, particle->m_seed);
  352. particle->m_angularVelocity.x = temp*(2*Stuff::Random::GetFraction() - 1.0f);
  353. particle->m_angularVelocity.y = temp*(2*Stuff::Random::GetFraction() - 1.0f);
  354. particle->m_angularVelocity.z = temp*(2*Stuff::Random::GetFraction() - 1.0f);
  355. }
  356. }
  357. //------------------------------------------------------------------------------
  358. //
  359. bool
  360. gosFX::DebrisCloud::Execute(struct gosFX::Effect::ExecuteInfo *info)
  361. {
  362. Check_Object(this);
  363. Check_Object(info);
  364. //
  365. //----------------------------------------
  366. // If we aren't supposed to execute, don't
  367. //----------------------------------------
  368. //
  369. if (!IsExecuted())
  370. return false;
  371. //
  372. //--------------------------------------------------------
  373. // Figure out the birth rate and request the new particles
  374. //--------------------------------------------------------
  375. //
  376. Specification *spec = GetSpecification();
  377. Check_Object(spec);
  378. Stuff::Scalar dT =
  379. static_cast<Stuff::Scalar>(info->m_time - m_lastRan);
  380. Verify(dT >= 0.0f);
  381. Stuff::Scalar prev_age = m_age;
  382. m_age += dT * m_ageRate;
  383. //
  384. //-----------------------------------
  385. // Deal with all the active particles
  386. //-----------------------------------
  387. //
  388. int i;
  389. Stuff::LinearMatrix4D local_to_world;
  390. local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
  391. for (i = 0; i < debrisPieces.GetLength(); i++)
  392. {
  393. //
  394. //--------------------------------------------------------------------
  395. // If the particle is active, age it and if it is not yet time to die,
  396. // go to the next particle, otherwise kill it
  397. //--------------------------------------------------------------------
  398. //
  399. Particle *particle = GetParticle(i);
  400. Check_Object(particle);
  401. if (particle->m_age < 1.0f)
  402. {
  403. particle->m_age += dT*particle->m_ageRate;
  404. if (AnimateParticle(i, &local_to_world, info->m_time))
  405. {
  406. continue;
  407. }
  408. DestroyParticle(i);
  409. }
  410. }
  411. //
  412. //----------------------------
  413. // Now let effect do its thing
  414. //----------------------------
  415. //
  416. m_age = prev_age;
  417. if(!Effect::Execute(info))
  418. return false;
  419. //
  420. //-------------------------------------------------------------------
  421. // If there is no bounds yet, we need to create our extent box around
  422. // the first legal point we find
  423. //-------------------------------------------------------------------
  424. //
  425. Stuff::ExtentBox box(Stuff::Point3D::Identity, Stuff::Point3D::Identity);
  426. for(i=0;i<debrisPieces.GetLength();i++)
  427. {
  428. Particle *particle = GetParticle(i);
  429. Check_Object(particle);
  430. //
  431. //-----------------------------------------------------------
  432. // We have found our first particle, so put the box around it
  433. //-----------------------------------------------------------
  434. //
  435. if (particle->m_age < 1.0f)
  436. {
  437. Stuff::Point3D point;
  438. Stuff::Scalar radius = spec->debrisSpheres[i].radius;
  439. point.Multiply(spec->debrisSpheres[i].center, particle->m_localToParent);
  440. box.maxX = point.x + radius;
  441. box.minX = point.x - radius;
  442. box.maxY = point.y + radius;
  443. box.minY = point.y - radius;
  444. box.maxZ = point.z + radius;
  445. box.minZ = point.z - radius;
  446. break;
  447. }
  448. i++;
  449. }
  450. //
  451. //-----------------------------
  452. // Look for the other particles
  453. //-----------------------------
  454. //
  455. while (i<debrisPieces.GetLength())
  456. {
  457. Particle *particle = GetParticle(i);
  458. Check_Object(particle);
  459. if (particle->m_age < 1.0f)
  460. {
  461. Stuff::ExtentBox local_box;
  462. Stuff::Point3D point;
  463. Stuff::Scalar radius = spec->debrisSpheres[i].radius;
  464. point.Multiply(spec->debrisSpheres[i].center, particle->m_localToParent);
  465. local_box.maxX = point.x + radius;
  466. local_box.minX = point.x - radius;
  467. local_box.maxY = point.y + radius;
  468. local_box.minY = point.y - radius;
  469. local_box.maxZ = point.z + radius;
  470. local_box.minZ = point.z - radius;
  471. box.Union(box, local_box);
  472. }
  473. i++;
  474. }
  475. //
  476. //------------------------------------
  477. // Now, build a info->m_bounds around this box
  478. //------------------------------------
  479. //
  480. Verify(box.maxX >= box.minX);
  481. Verify(box.maxY >= box.minY);
  482. Verify(box.maxZ >= box.minZ);
  483. Stuff::OBB local_bounds = Stuff::OBB::Identity;
  484. local_bounds.axisExtents.x = 0.5f * (box.maxX - box.minX);
  485. local_bounds.axisExtents.y = 0.5f * (box.maxY - box.minY);
  486. local_bounds.axisExtents.z = 0.5f * (box.maxZ - box.minZ);
  487. local_bounds.localToParent(3,0) = box.minX + local_bounds.axisExtents.x;
  488. local_bounds.localToParent(3,1) = box.minY + local_bounds.axisExtents.y;
  489. local_bounds.localToParent(3,2) = box.minZ + local_bounds.axisExtents.z;
  490. local_bounds.sphereRadius = local_bounds.axisExtents.GetLength();
  491. if (local_bounds.sphereRadius < Stuff::SMALL)
  492. local_bounds.sphereRadius = 0.01f;
  493. Stuff::OBB parent_bounds;
  494. parent_bounds.Multiply(local_bounds, m_localToParent);
  495. info->m_bounds->Union(*info->m_bounds, parent_bounds);
  496. //
  497. //----------------------------------------------
  498. // Tell our caller that we get to keep executing
  499. //----------------------------------------------
  500. //
  501. return true;
  502. }
  503. //------------------------------------------------------------------------------
  504. //
  505. bool
  506. gosFX::DebrisCloud::HasFinished(void)
  507. {
  508. Check_Object(this);
  509. return Effect::HasFinished();
  510. }
  511. //------------------------------------------------------------------------------
  512. //
  513. void
  514. gosFX::DebrisCloud::Kill(void)
  515. {
  516. Check_Object(this);
  517. //
  518. //-------------------------------------------------------------
  519. // Destroy all the particles and set up an empty particle cloud
  520. //-------------------------------------------------------------
  521. //
  522. for(int i=0; i < debrisPieces.GetLength(); i++)
  523. {
  524. DestroyParticle(i);
  525. }
  526. //
  527. //----------------------------------------
  528. // Now let the base effect handle stopping
  529. //----------------------------------------
  530. //
  531. Effect::Kill();
  532. }
  533. //------------------------------------------------------------------------------
  534. //
  535. bool
  536. gosFX::DebrisCloud::AnimateParticle(
  537. unsigned index,
  538. const Stuff::LinearMatrix4D *world_to_new_local,
  539. Stuff::Time till
  540. )
  541. {
  542. Check_Object(this);
  543. //
  544. //-----------------------------------------
  545. // Animate the parent then get our pointers
  546. //-----------------------------------------
  547. //
  548. Specification *spec = GetSpecification();
  549. Check_Object(spec);
  550. Particle *particle = GetParticle(index);
  551. Check_Object(particle);
  552. Stuff::Scalar seed = particle->m_seed;
  553. Stuff::Scalar age = particle->m_age;
  554. if (age >= 1.0f)
  555. return false;
  556. //
  557. //------------------
  558. // Animate the color
  559. //------------------
  560. //
  561. Set_Statistic(Shape_Count, Shape_Count+1);
  562. particle->m_alpha = spec->m_pAlpha.ComputeValue(age, seed);
  563. //
  564. //-----------------------------------------------------------------------
  565. // If this cloud is unparented, we need to transform the point from local
  566. // space into world space and set the internal position/velocity pointers
  567. // to these temporary values
  568. //-----------------------------------------------------------------------
  569. //
  570. Stuff::Point3D translation;
  571. translation = particle->m_localToParent;
  572. Stuff::UnitQuaternion rotation;
  573. rotation = particle->m_localToParent;
  574. //
  575. //------------------------------------------------------------------
  576. // First, calculate the drag on the particle. Drag can never assist
  577. // velocity
  578. //------------------------------------------------------------------
  579. //
  580. Stuff::Scalar drag = -spec->m_pDrag.ComputeValue(age, seed);
  581. Max_Clamp(drag, 0.0f);
  582. Stuff::Vector3D ether;
  583. ether.x = 0.0f;
  584. ether.y = spec->m_pEtherVelocityY.ComputeValue(age, seed);
  585. ether.z = 0.0f;
  586. Stuff::Vector3D accel(Stuff::Vector3D::Identity);
  587. //
  588. //-------------------------------------------------------------------
  589. // Deal with pseudo-world simulation. In this mode, we interpret the
  590. // forces as if they are already in worldspace, and we transform them
  591. // back to local space
  592. //-------------------------------------------------------------------
  593. //
  594. Stuff::LinearMatrix4D world_to_effect;
  595. world_to_effect.Invert(m_localToWorld);
  596. Stuff::Vector3D local_ether;
  597. local_ether.MultiplyByInverse(ether, world_to_effect);
  598. Stuff::Vector3D rel_vel;
  599. rel_vel.Subtract(particle->m_linearVelocity, local_ether);
  600. accel.Multiply(rel_vel, drag);
  601. //
  602. //-----------------------------------------
  603. // Now, add in acceleration of the particle
  604. //-----------------------------------------
  605. //
  606. Stuff::Vector3D world_accel;
  607. world_accel.x = 0.0f;
  608. world_accel.y = spec->m_pAccelerationY.ComputeValue(age, seed);
  609. world_accel.z = 0.0f;
  610. Stuff::Vector3D local_accel;
  611. local_accel.Multiply(world_accel, world_to_effect);
  612. accel += local_accel;
  613. //
  614. //-------------------------------------------------
  615. // Compute the particle's new velocity and position
  616. //-------------------------------------------------
  617. //
  618. Stuff::Scalar time_slice =
  619. static_cast<Stuff::Scalar>(till - m_lastRan);
  620. particle->m_linearVelocity.AddScaled(particle->m_linearVelocity, accel, time_slice);
  621. translation.AddScaled(translation, particle->m_linearVelocity, time_slice);
  622. //
  623. //-----------------------
  624. // Deal with the rotation
  625. //-----------------------
  626. //
  627. Stuff::Vector3D omega(particle->m_angularVelocity);
  628. omega *= time_slice;
  629. Stuff::UnitQuaternion omega_q;
  630. omega_q = omega;
  631. rotation.Multiply(omega_q, Stuff::UnitQuaternion(rotation));
  632. rotation.Normalize();
  633. particle->m_localToParent.BuildRotation(rotation);
  634. particle->m_localToParent.BuildTranslation(translation);
  635. Check_Object(&particle->m_localToParent);
  636. return true;
  637. }
  638. //------------------------------------------------------------------------------
  639. //
  640. void
  641. gosFX::DebrisCloud::DestroyParticle(unsigned int index)
  642. {
  643. Particle *particle = GetParticle(index);
  644. Check_Object(particle);
  645. particle->m_age = 1.0f;
  646. }
  647. //------------------------------------------------------------------------------
  648. //
  649. void gosFX::DebrisCloud::Draw(DrawInfo *info)
  650. {
  651. Check_Object(this);
  652. Check_Object(info);
  653. Check_Object(info->m_parentToWorld);
  654. //
  655. //----------------------------
  656. // Set up the common draw info
  657. //----------------------------
  658. //
  659. Specification *spec = GetSpecification();
  660. Check_Object(spec);
  661. int i, nrOfParticle = debrisPieces.GetLength();
  662. for(i=0;i<nrOfParticle;i++)
  663. {
  664. //
  665. //-----------------------------------------------------------------
  666. // If the particle is still alive, concatenate into world space and
  667. // issue the draw command
  668. //-----------------------------------------------------------------
  669. //
  670. Particle *particle = GetParticle(i);
  671. Check_Object(particle);
  672. if (particle->m_age < 1.0f)
  673. {
  674. MidLevelRenderer::DrawScalableShapeInformation dinfo;
  675. MidLevelRenderer::MLRShape *shape = spec->debrisPieces[i];
  676. dinfo.clippingFlags.SetClippingState(0x3f);
  677. dinfo.worldToShape = NULL;
  678. dinfo.state.Combine(info->m_state, spec->m_state);
  679. dinfo.activeLights = NULL;
  680. dinfo.nrOfActiveLights = 0;
  681. dinfo.shape = shape;
  682. Stuff::LinearMatrix4D local_to_world;
  683. local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
  684. //
  685. //---------------------------------------------------------------
  686. // No alignment is necessary, so just multiply out all the active
  687. // particles
  688. //---------------------------------------------------------------
  689. //
  690. Stuff::LinearMatrix4D shape_to_world;
  691. shape_to_world.Multiply(
  692. particle->m_localToParent,
  693. local_to_world
  694. );
  695. dinfo.shapeToWorld = &shape_to_world;
  696. dinfo.scaling = NULL;
  697. Stuff::RGBAColor color(1.0f, 1.0f, 1.0f, particle->m_alpha);
  698. dinfo.paintMe = &color;
  699. info->m_clipper->DrawScalableShape(&dinfo);
  700. }
  701. }
  702. //
  703. //----------------------------
  704. // Let our parent do its thing
  705. //----------------------------
  706. //
  707. Effect::Draw(info);
  708. }
  709. //------------------------------------------------------------------------------
  710. //
  711. void
  712. gosFX::DebrisCloud::TestInstance() const
  713. {
  714. Verify(IsDerivedFrom(DefaultData));
  715. }