efgeo.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Mine Field Geo
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. class MineFieldGeoImpl : public MineFieldGeo {
  8. private:
  9. TRef<Surface> m_psurface;
  10. TVector<Vector> m_vposition;
  11. float m_radius;
  12. static int GetCount(float strength, float radius)
  13. {
  14. return 1 + int(strength * radius * radius / 100.0f);
  15. }
  16. public:
  17. MineFieldGeoImpl(Surface* psurface, float strength, float radius) :
  18. m_psurface(psurface),
  19. m_vposition(GetCount(strength, radius)),
  20. m_radius(radius)
  21. {
  22. for (int index = 0; index < m_vposition.GetCount(); index++) {
  23. m_vposition.Set(index, Vector::RandomPosition(radius));
  24. }
  25. }
  26. //////////////////////////////////////////////////////////////////////////////
  27. //
  28. // MineFieldGeo methods
  29. //
  30. //////////////////////////////////////////////////////////////////////////////
  31. void SetStrength(float strength)
  32. {
  33. int count = GetCount(strength, m_radius);
  34. ZAssert(count <= m_vposition.GetCount());
  35. m_vposition.SetCount(count);
  36. Changed();
  37. }
  38. //////////////////////////////////////////////////////////////////////////////
  39. //
  40. // Geo Methods
  41. //
  42. //////////////////////////////////////////////////////////////////////////////
  43. float GetRadius(const Matrix& mat)
  44. {
  45. return m_radius;
  46. }
  47. void Render(Context* pcontext)
  48. {
  49. Vector vecEye = pcontext->TransformLocalToEye(Vector::GetZero());
  50. float bright = bound(100.0f / vecEye.Length(), 0.0f, 1.0f);
  51. if (bright > 0) {
  52. Color color(bright, bright, bright);
  53. int count = m_vposition.GetCount();
  54. for (int index = 0; index < count; index++) {
  55. pcontext->DrawDecal(
  56. m_psurface,
  57. color,
  58. m_vposition[index],
  59. Vector::GetZero(),
  60. Vector::GetZero(),
  61. 1,
  62. 0,
  63. BlendModeSource
  64. );
  65. }
  66. }
  67. }
  68. };
  69. TRef<MineFieldGeo> CreateMineFieldGeo(Surface* psurface, float strength, float radius)
  70. {
  71. return new MineFieldGeoImpl(psurface, strength, radius);
  72. }
  73. //////////////////////////////////////////////////////////////////////////////
  74. //
  75. // Build Effect Geo
  76. //
  77. //////////////////////////////////////////////////////////////////////////////
  78. const float c_ratio = 1.1f;
  79. class BuildEffectGeoImpl :
  80. public BuildEffectGeo,
  81. public IGeoCallback
  82. {
  83. private:
  84. Color m_colorInner;
  85. Color m_colorOuter;
  86. Color m_colorComplement;
  87. TRef<Geo> m_psphere;
  88. float m_time;
  89. float m_radius;
  90. float m_fOuter;
  91. Vector m_position;
  92. public:
  93. BuildEffectGeoImpl(
  94. Modeler* pmodeler,
  95. Number* ptime,
  96. const Color& color
  97. ) :
  98. BuildEffectGeo(ptime),
  99. m_colorOuter(color)
  100. {
  101. float h;
  102. float s;
  103. float b;
  104. m_colorOuter.GetHSB(h, s, b);
  105. m_colorComplement.SetHSBA(h + 0.5f, s, b);
  106. m_psphere = pmodeler->LoadGeo("build");
  107. }
  108. //////////////////////////////////////////////////////////////////////////////
  109. //
  110. // BuildEffectGeo Methods
  111. //
  112. //////////////////////////////////////////////////////////////////////////////
  113. float GetRadius()
  114. {
  115. return m_radius;
  116. }
  117. void SetRadius(float f)
  118. {
  119. m_radius = f;
  120. }
  121. const Vector& GetPosition()
  122. {
  123. return m_position;
  124. }
  125. void SetPosition(const Vector& p)
  126. {
  127. m_position = p;
  128. }
  129. void SetColors(float aInner, float fInner, float fOuter)
  130. {
  131. m_colorInner = m_colorComplement * fInner;
  132. m_colorInner.SetAlpha(aInner);
  133. m_fOuter = fOuter;
  134. }
  135. //////////////////////////////////////////////////////////////////////////////
  136. //
  137. // Geo Methods
  138. //
  139. //////////////////////////////////////////////////////////////////////////////
  140. void Evaluate()
  141. {
  142. m_time = GetTime()->GetValue();
  143. }
  144. void Render(Context* pcontext)
  145. {
  146. pcontext->DrawCallbackGeo(this, true);
  147. }
  148. void RenderCallback(Context* pcontext)
  149. {
  150. //
  151. // Rendering modes
  152. //
  153. pcontext->SetBlendMode(BlendModeSourceAlpha);
  154. pcontext->SetShadeMode(ShadeModeGlobalColor);
  155. //
  156. //
  157. //
  158. pcontext->Translate(m_position);
  159. pcontext->Scale3(m_radius);
  160. //
  161. // inner sphere
  162. //
  163. pcontext->PushState();
  164. pcontext->Scale3(1.0f / c_ratio);
  165. pcontext->Rotate(Vector(0, 0, 1), m_time / pi);
  166. pcontext->Rotate(Vector(0, 1, 0), 0.5f * pi * m_time);
  167. pcontext->SetGlobalColor(m_colorInner);
  168. m_psphere->Render(pcontext);
  169. pcontext->PopState();
  170. //
  171. // outer sphere
  172. //
  173. pcontext->Rotate(Vector(1, 0, 0), m_time);
  174. pcontext->Rotate(Vector(0, 1, 0), pi * m_time);
  175. pcontext->SetBlendMode(BlendModeAdd);
  176. pcontext->SetGlobalColor(m_colorOuter * m_fOuter);
  177. m_psphere->Render(pcontext);
  178. }
  179. };
  180. TRef<BuildEffectGeo> CreateBuildEffectGeo(
  181. Modeler* pmodeler,
  182. Number* ptime,
  183. const Color& color
  184. ) {
  185. return
  186. new BuildEffectGeoImpl(
  187. pmodeler,
  188. ptime,
  189. color
  190. );
  191. }
  192. //////////////////////////////////////////////////////////////////////////////
  193. //
  194. // WireSphere
  195. //
  196. //////////////////////////////////////////////////////////////////////////////
  197. class WireSphereGeo : public Geo {
  198. private:
  199. TVector<VertexL> m_vertices;
  200. TVector<MeshIndex> m_indices;
  201. static const int vSegments;
  202. public:
  203. WireSphereGeo(float minDot, int hSegments) :
  204. m_vertices(
  205. hSegments * (vSegments - 1),
  206. hSegments * (vSegments - 1)
  207. ),
  208. m_indices(
  209. 2 * hSegments * (vSegments * 2 - 3),
  210. 2 * hSegments * (vSegments * 2 - 3)
  211. )
  212. {
  213. //
  214. // Create the vertex array
  215. //
  216. int vIndex;
  217. int hIndex;
  218. for (vIndex = 0; vIndex < vSegments - 1; vIndex++)
  219. {
  220. float vSin = minDot - float(vIndex) * 0.05f;
  221. float vCos = float(sqrt(1.0f - vSin * vSin));
  222. for (hIndex = 0; hIndex < hSegments; hIndex++)
  223. {
  224. int index = vIndex * hSegments + hIndex;
  225. float hAngle = (float)hIndex * 2.0f * pi / (float)hSegments;
  226. float x = cos(hAngle) * vCos;
  227. float y = sin(hAngle) * vCos;
  228. float z = -vSin;
  229. static const float intensity = 1.0f;
  230. m_vertices.Set(
  231. index,
  232. VertexL(
  233. 1000 * x,
  234. 1000 * y,
  235. 1000 * z,
  236. intensity,
  237. intensity,
  238. intensity,
  239. 1,
  240. 0,
  241. 0
  242. )
  243. );
  244. }
  245. }
  246. //
  247. // Vertical lines
  248. //
  249. int index = 0;
  250. for (vIndex = 0; vIndex < vSegments - 2; vIndex++) {
  251. for (hIndex = 0; hIndex < hSegments; hIndex++) {
  252. m_indices.Set(index , vIndex * hSegments + hIndex);
  253. m_indices.Set(index + 1, (vIndex + 1) * hSegments + hIndex);
  254. ZAssert(m_indices[index ] >= 0 && m_indices[index ] < m_vertices.GetCount());
  255. ZAssert(m_indices[index + 1] >= 0 && m_indices[index + 1] < m_vertices.GetCount());
  256. index += 2;
  257. }
  258. }
  259. //
  260. // Horizontal lines
  261. //
  262. for (vIndex = 0; vIndex < vSegments - 1; vIndex++) {
  263. for (hIndex = 0; hIndex < hSegments; hIndex++) {
  264. m_indices.Set(index, vIndex * hSegments + hIndex);
  265. m_indices.Set(index + 1,
  266. hIndex == hSegments - 1 ?
  267. vIndex * hSegments
  268. : vIndex * hSegments + hIndex + 1
  269. );
  270. ZAssert(m_indices[index ] >= 0 && m_indices[index ] < m_vertices.GetCount());
  271. ZAssert(m_indices[index + 1] >= 0 && m_indices[index + 1] < m_vertices.GetCount());
  272. index += 2;
  273. }
  274. }
  275. ZAssert(index == m_indices.GetCount());
  276. }
  277. void Render(Context* pcontext)
  278. {
  279. pcontext->DrawLines(m_vertices, m_indices);
  280. }
  281. //
  282. // Value members
  283. //
  284. ZString GetFunctionName() { return "WireSphereGeo"; }
  285. };
  286. const int WireSphereGeo::vSegments = 3;
  287. TRef<Geo> CreateWireSphereGeo(float minDot, int hSegments)
  288. {
  289. return new WireSphereGeo(minDot, hSegments);
  290. }
  291. //////////////////////////////////////////////////////////////////////////////
  292. //
  293. // Pulse Geo
  294. //
  295. //////////////////////////////////////////////////////////////////////////////
  296. class PulseGeoImpl :
  297. public PulseGeo,
  298. public IGeoCallback
  299. {
  300. protected:
  301. class WhiteSurfaceSite : public SurfaceSite {
  302. public:
  303. void UpdateSurface(Surface* psurface)
  304. {
  305. psurface->FillSurface(Color::White());
  306. }
  307. };
  308. struct PulseData : public IObject
  309. {
  310. float m_fRadius;
  311. Vector m_vecPosition;
  312. Color m_color;
  313. float m_fStartTime;
  314. float m_fExplodeTime;
  315. PulseData (float fStartTime, float fExplodeTime, float fRadius, const Vector& vecPosition, const Color& color)
  316. {
  317. m_fRadius = fRadius;
  318. m_vecPosition = vecPosition;
  319. m_color = color;
  320. m_fStartTime = fStartTime;
  321. m_fExplodeTime = fExplodeTime;
  322. }
  323. };
  324. TList<TRef<PulseData> > m_pulseData;
  325. float m_fTime;
  326. TRef<Geo> m_pSphere;
  327. TRef<Surface> m_pTexture;
  328. public:
  329. PulseGeoImpl (Modeler* pmodeler, Number* ptime) : PulseGeo (ptime)
  330. {
  331. m_pSphere = pmodeler->LoadGeo("aleph_sphere");
  332. m_pTexture = pmodeler->GetEngine ()->CreateSurface (WinPoint (16, 16), SurfaceType2D (), new WhiteSurfaceSite());
  333. }
  334. void AddPulse (float fExplodeTime, float fRadius, const Vector& vecPosition, const Color& color)
  335. {
  336. float fStartTime = GetTime()->GetValue();
  337. m_pulseData.PushFront (new PulseData (fStartTime, fExplodeTime, (fRadius / m_pSphere->GetRadius (Matrix::GetIdentity ())) * 0.5f, vecPosition, color));
  338. }
  339. void Evaluate()
  340. {
  341. m_fTime = GetTime()->GetValue();
  342. }
  343. void Render(Context* pcontext)
  344. {
  345. pcontext->DrawCallbackGeo(this, true);
  346. }
  347. void RenderCallback(Context* pcontext)
  348. {
  349. TList<TRef<PulseData> >::Iterator iter (m_pulseData);
  350. // Rendering modes
  351. pcontext->SetBlendMode (BlendModeAdd);
  352. pcontext->SetShadeMode (ShadeModeGlobalColor);
  353. pcontext->SetTexture (m_pTexture);
  354. while (! iter.End ())
  355. {
  356. TRef<PulseData> pGeo = iter.Value ();
  357. // compute the time
  358. float fTimeUntilExplosion = pGeo->m_fExplodeTime - (m_fTime - pGeo->m_fStartTime);
  359. float fEffectDuration = 0.5f;
  360. if (fTimeUntilExplosion <= fEffectDuration)
  361. {
  362. if (fTimeUntilExplosion <= -fEffectDuration)
  363. {
  364. // the effect has expired, so remove this node and move on to the next one
  365. iter.Remove ();
  366. }
  367. else
  368. {
  369. // compute the factor that gives us the growth and opacity of the effect
  370. float fEffectScale = 1.0f - fabsf (fTimeUntilExplosion / fEffectDuration);
  371. assert (fEffectScale <= 1.0f);
  372. fEffectScale *= fEffectScale;
  373. // transformations
  374. pcontext->Translate(pGeo->m_vecPosition);
  375. pcontext->Scale3(pGeo->m_fRadius * fEffectScale);
  376. // do the rendering
  377. pcontext->PushState ();
  378. pcontext->SetGlobalColor (Color (pGeo->m_color.R () * fEffectScale, pGeo->m_color.G () * fEffectScale, pGeo->m_color.B () * fEffectScale, fEffectScale));
  379. m_pSphere->Render (pcontext);
  380. pcontext->PopState ();
  381. // skip to the next node in the list
  382. iter.Next ();
  383. }
  384. }
  385. else
  386. {
  387. // skip to the next node in the list
  388. iter.Next ();
  389. }
  390. }
  391. }
  392. };
  393. TRef<PulseGeo> CreatePulseGeo(Modeler* pmodeler, Number* ptime)
  394. {
  395. return new PulseGeoImpl (pmodeler, ptime);
  396. }
  397. //////////////////////////////////////////////////////////////////////////////
  398. //
  399. // Trail Geo
  400. //
  401. //////////////////////////////////////////////////////////////////////////////
  402. const int maxSections = 16;
  403. const float timeDelta = 0.5f;
  404. class TrailGeo : public Geo, public IGeoCallback {
  405. private:
  406. TVector<VertexL> m_vertices;
  407. TVector<MeshIndex> m_indices;
  408. int m_section;
  409. float m_timeLast;
  410. Color m_color;
  411. TRef<Image> m_pimage;
  412. Vector m_vecRightLast;
  413. Number* GetTime() { return Number::Cast(GetChild(0)); }
  414. VectorValue* GetPosition() { return VectorValue::Cast(GetChild(1)); }
  415. VectorValue* GetRight() { return VectorValue::Cast(GetChild(2)); }
  416. Boolean* GetMoving() { return Boolean::Cast(GetChild(3)); }
  417. public:
  418. TrailGeo(
  419. Modeler* pmodeler,
  420. const Color& color,
  421. VectorValue* pvectorPosition,
  422. VectorValue* pvectorRight,
  423. Boolean* pbooleanMoving,
  424. Number* ptime
  425. ) :
  426. Geo(ptime, pvectorPosition, pvectorRight, pbooleanMoving),
  427. m_color(color),
  428. m_vecRightLast(pvectorRight->GetValue()),
  429. m_vertices((maxSections + 1) * 2, (maxSections + 1) * 2),
  430. m_indices(maxSections * 6, maxSections * 6),
  431. m_section(0),
  432. m_timeLast(-1)
  433. {
  434. m_pimage = pmodeler->LoadImage(AWF_EFFECT_TRAIL, true);
  435. int index;
  436. for(index = 0; index < maxSections; index ++) {
  437. int indexVertex = index * 2;
  438. int indexIndex = index * 6;
  439. m_indices.Set(indexIndex + 0, indexVertex + 0);
  440. m_indices.Set(indexIndex + 1, indexVertex + 2);
  441. m_indices.Set(indexIndex + 2, indexVertex + 3);
  442. m_indices.Set(indexIndex + 3, indexVertex + 0);
  443. m_indices.Set(indexIndex + 4, indexVertex + 3);
  444. m_indices.Set(indexIndex + 5, indexVertex + 1);
  445. }
  446. int count = m_vertices.GetCount();
  447. for(index = 0; index < count; index += 2) {
  448. m_vertices.Get(index ).SetTextureCoordinate(Point(0, 0));
  449. m_vertices.Get(index + 1).SetTextureCoordinate(Point(1, 0));
  450. }
  451. }
  452. void UpdateColors(float time)
  453. {
  454. if (m_section != 0) {
  455. float dtime = (time - m_timeLast) / (timeDelta * maxSections);
  456. float bright = 1 - dtime;
  457. float dbright = 1.0f / maxSections;
  458. for (int index = 0; index <= m_section; index++) {
  459. Color color = m_color * bright;
  460. bright -= dbright;
  461. if (bright < 0) {
  462. bright = 0;
  463. }
  464. m_vertices.Get(index * 2 ).SetColor(color);
  465. m_vertices.Get(index * 2 + 1).SetColor(color);
  466. }
  467. }
  468. }
  469. void Evaluate()
  470. {
  471. float time = GetTime()->GetValue();
  472. const Vector& vecPos = GetPosition()->GetValue();
  473. const Vector& vecRight = GetRight()->GetValue();
  474. bool bMoving = GetMoving()->GetValue();
  475. if (vecPos != Vector(0, 0, 0)) {
  476. if (m_timeLast == -1) {
  477. m_timeLast = time;
  478. } else {
  479. if (time - m_timeLast > timeDelta) {
  480. m_timeLast = time;
  481. if (m_section < maxSections) {
  482. m_section++;
  483. }
  484. for(int index = m_section * 2 + 1; index > 1; index--) {
  485. m_vertices.Set(index, m_vertices[index - 2]);
  486. }
  487. }
  488. }
  489. if (bMoving) {
  490. m_vecRightLast = vecRight;
  491. }
  492. m_vertices.Get(0).SetPosition(vecPos - m_vecRightLast);
  493. m_vertices.Get(1).SetPosition(vecPos + m_vecRightLast);
  494. UpdateColors(time);
  495. }
  496. }
  497. void Render(Context* pcontext)
  498. {
  499. pcontext->DrawCallbackGeo(this, true);
  500. }
  501. void RenderCallback(Context* pcontext)
  502. {
  503. pcontext->SetMaterial(NULL);
  504. pcontext->SetShadeMode(ShadeModeGouraud);
  505. pcontext->SetCullMode(CullModeNone);
  506. pcontext->SetBlendMode(BlendModeAdd);
  507. pcontext->SetZWrite(false);
  508. pcontext->SetTexture(m_pimage->GetSurface());
  509. if (m_section != 0) {
  510. pcontext->DrawTriangles(
  511. &m_vertices[0],
  512. (m_section + 1) * 2,
  513. &m_indices[0],
  514. m_section * 6
  515. );
  516. }
  517. }
  518. };
  519. TRef<Geo> CreateTrailGeo(
  520. Modeler* pmodeler,
  521. const Color& color,
  522. VectorValue* pvectorPosition,
  523. VectorValue* pvectorRight,
  524. Boolean* pbooleanMoving,
  525. Number* ptime
  526. ) {
  527. return new TrailGeo(pmodeler, color, pvectorPosition, pvectorRight, pbooleanMoving, ptime);
  528. }
  529. //////////////////////////////////////////////////////////////////////////////
  530. //
  531. // HullHitGeo
  532. //
  533. //////////////////////////////////////////////////////////////////////////////
  534. class HullHitGeoImpl : public HullHitGeo {
  535. private:
  536. class HullHitData {
  537. public:
  538. Vector m_position;
  539. Vector m_normal;
  540. Vector m_forward;
  541. Vector m_right;
  542. float m_timeStart;
  543. };
  544. typedef TList<HullHitData, DefaultNoEquals> HullHitDataList;
  545. HullHitDataList m_listHullHitData;
  546. TRef<Surface> m_psurfaceNormal;
  547. TRef<Surface> m_psurfaceTangent;
  548. Number* GetTime() { return Number::Cast(GetChild(0)); }
  549. public:
  550. HullHitGeoImpl(Modeler* pmodeler, Number* ptime) :
  551. HullHitGeo(ptime)
  552. {
  553. m_psurfaceNormal = pmodeler->LoadSurface(AWF_EFFECT_NORMAL, true);
  554. m_psurfaceTangent = pmodeler->LoadSurface(AWF_EFFECT_TANGENT, true);
  555. }
  556. void AddHullHit(const Vector& vecPosition, const Vector& vecNormal)
  557. {
  558. m_listHullHitData.PushFront();
  559. HullHitData& data = m_listHullHitData.GetFront();
  560. data.m_position = vecPosition;
  561. data.m_normal = vecNormal;
  562. if (vecNormal == Vector(0, 0, 1)) {
  563. data.m_forward = CrossProduct(vecNormal, Vector(0, 1, 0)).Normalize();
  564. } else {
  565. data.m_forward = CrossProduct(vecNormal, Vector(0, 0, 1)).Normalize();
  566. }
  567. data.m_right = CrossProduct(data.m_forward, vecNormal);
  568. data.m_timeStart = GetTime()->GetValue();
  569. }
  570. void Render(Context* pcontext)
  571. {
  572. float timeCurrent = GetTime()->GetValue();
  573. HullHitDataList::Iterator iter(m_listHullHitData);
  574. while (!iter.End()) {
  575. HullHitData& data = iter.Value();
  576. Color color(1, 1, 1);
  577. float maxSize = 2.0f;
  578. float scale = 0.1f + maxSize * 5.0f * (timeCurrent - data.m_timeStart);
  579. if (scale > maxSize) {
  580. scale = maxSize;
  581. }
  582. //
  583. // draw the tangent decal
  584. //
  585. pcontext->DrawDecal(
  586. m_psurfaceTangent,
  587. color,
  588. data.m_position,
  589. scale * data.m_forward,
  590. scale * data.m_right,
  591. 1,
  592. 0
  593. );
  594. //
  595. // draw the normal decal
  596. //
  597. pcontext->DrawDecal(
  598. m_psurfaceNormal,
  599. color,
  600. data.m_position + scale * data.m_normal,
  601. scale * data.m_normal,
  602. Vector(0, 0, 0),
  603. 1,
  604. 0
  605. );
  606. //
  607. // Remove it if it's reached fullsize
  608. //
  609. if (scale == maxSize) {
  610. iter.Remove();
  611. } else {
  612. iter.Next();
  613. }
  614. }
  615. }
  616. };
  617. TRef<HullHitGeo> CreateHullHitGeo(Modeler* pmodeler, Number* ptime)
  618. {
  619. return new HullHitGeoImpl(pmodeler, ptime);
  620. }
  621. //////////////////////////////////////////////////////////////////////////////
  622. //
  623. // BitsGeo
  624. //
  625. //////////////////////////////////////////////////////////////////////////////
  626. const int g_maxBits = 32;
  627. const int g_bitsLifeTime = 2;
  628. class BitsGeoImpl : public BitsGeo {
  629. private:
  630. typedef TRange<g_maxBits> BitsRange;
  631. class BitsData {
  632. public:
  633. Vector m_vecPosition;
  634. Vector m_dvecPosition;
  635. Vector m_axis;
  636. float m_speed;
  637. float m_time;
  638. float m_size;
  639. };
  640. BitsData m_data[g_maxBits];
  641. TRef<Geo> m_pgeo;
  642. BitsRange m_indexFirst;
  643. BitsRange m_indexLast;
  644. float m_time;
  645. Number* GetTime() { return Number::Cast(GetChild(0)); }
  646. public:
  647. BitsGeoImpl(Modeler* pmodeler, Number* ptime) :
  648. BitsGeo(ptime),
  649. m_indexFirst(0),
  650. m_indexLast(0),
  651. m_time(ptime->GetValue())
  652. {
  653. m_pgeo = pmodeler->LoadGeo(AWF_EFFECT_BIT);
  654. }
  655. void AddBit(
  656. const Vector& vecPosition,
  657. const Vector& dvecPosition,
  658. float size
  659. ) {
  660. --m_indexFirst;
  661. if (m_indexFirst == m_indexLast) {
  662. --m_indexLast;
  663. }
  664. m_data[m_indexFirst].m_time = m_time;
  665. m_data[m_indexFirst].m_vecPosition = vecPosition;
  666. m_data[m_indexFirst].m_dvecPosition = dvecPosition;
  667. m_data[m_indexFirst].m_axis = Vector::RandomDirection();
  668. m_data[m_indexFirst].m_speed = random(pi /2, 2 * pi);
  669. m_data[m_indexFirst].m_size = size;
  670. }
  671. void Evaluate()
  672. {
  673. m_time = GetTime()->GetValue();
  674. }
  675. void Render(Context* pcontext)
  676. {
  677. if (m_indexFirst != m_indexLast) {
  678. for(BitsRange index = m_indexFirst; index != m_indexLast; ++index) {
  679. BitsData& data = m_data[index];
  680. float dtime = m_time - data.m_time;
  681. if (dtime > g_bitsLifeTime) {
  682. m_indexLast = index;
  683. break;
  684. }
  685. Vector position = data.m_vecPosition + data.m_dvecPosition * dtime;
  686. pcontext->PushState();
  687. pcontext->Translate(position);
  688. pcontext->Scale3(data.m_size);
  689. pcontext->Rotate(data.m_axis, data.m_speed * dtime);
  690. m_pgeo->Render(pcontext);
  691. pcontext->PopState();
  692. }
  693. }
  694. }
  695. };
  696. TRef<BitsGeo> CreateBitsGeo(Modeler* pmodeler, Number* ptime)
  697. {
  698. return new BitsGeoImpl(pmodeler, ptime);
  699. }
  700. //////////////////////////////////////////////////////////////////////////////
  701. //
  702. // BoltGeo
  703. //
  704. //////////////////////////////////////////////////////////////////////////////
  705. class BoltGeo : public Geo, IGeoCallback {
  706. private:
  707. TRef<Surface> m_psurface;
  708. float m_size;
  709. VectorValue* GetStart() { return VectorValue::Cast(GetChild(0)); }
  710. VectorValue* GetEnd() { return VectorValue::Cast(GetChild(1)); }
  711. public:
  712. BoltGeo(VectorValue* pstart, VectorValue* pend, float size, Surface* psurface) :
  713. Geo(pstart, pend),
  714. m_size(size),
  715. m_psurface(psurface)
  716. {
  717. }
  718. void Render(Context* pcontext)
  719. {
  720. pcontext->DrawCallbackGeo(this, false);
  721. }
  722. void RenderCallback(Context* pcontext)
  723. {
  724. int index;
  725. //
  726. // Find two orthogonal vectors
  727. //
  728. Vector vecStart = GetStart()->GetValue();
  729. Vector vecEnd = GetEnd()->GetValue();
  730. Vector vecForward = vecEnd - vecStart;
  731. Vector vecUp = vecForward.GetOrthogonalVector().Normalize();
  732. Vector vecRight = CrossProduct(vecForward, vecUp).Normalize();
  733. float length = vecForward.Length();
  734. float size = m_size * length;
  735. //
  736. // Calculate the level of detail
  737. //
  738. float lengthImage =
  739. max(
  740. pcontext->GetImageRadius(vecStart, size),
  741. pcontext->GetImageRadius(vecEnd, size)
  742. );
  743. int lcount;
  744. if (lengthImage > 128) {
  745. lcount = 6;
  746. } else if (lengthImage > 64) {
  747. lcount = 5;
  748. } else if (lengthImage > 32) {
  749. lcount = 4;
  750. } else {
  751. lcount = 3;
  752. }
  753. //
  754. // color is based on size
  755. //
  756. float bright = min(1.0f, lengthImage / 128);
  757. Color color(bright, bright, bright);
  758. //
  759. // allocate the vertex and index buffers
  760. //
  761. int vcount = (1 << lcount) + 1;
  762. VertexL* pvertex = pcontext->GetVertexLBuffer(vcount);
  763. for (index = 0; index < vcount; index++) {
  764. pvertex[index].SetColor(color);
  765. pvertex[index].SetTextureCoordinate(
  766. Point(
  767. (float)index / (float)(vcount - 1),
  768. 0
  769. )
  770. );
  771. }
  772. //
  773. // sub divide
  774. //
  775. pvertex[0].SetPosition(vecStart);
  776. pvertex[vcount - 1].SetPosition(vecEnd);
  777. for (int level = lcount; level > 0 ; level--) {
  778. int dbig = 1 << level;
  779. int dsmall = dbig / 2;
  780. for (index = dsmall; index < vcount; index += dbig) {
  781. float angle = random(0, 2 * pi);
  782. VertexL& vecFirst = pvertex[index - dsmall];
  783. VertexL& vecLast = pvertex[index + dsmall];
  784. Vector vecMiddle = 0.5f * (vecFirst.GetPosition() + vecLast.GetPosition());
  785. Vector vecRandom = size * (cos(angle) * vecUp + sin(angle) * vecRight);
  786. pvertex[index].SetPosition(vecMiddle + vecRandom);
  787. }
  788. size = size / 2;
  789. }
  790. //
  791. // draw it
  792. //
  793. pcontext->SetTexture(m_psurface);
  794. pcontext->SetLineWidth(4);
  795. pcontext->SetBlendMode(BlendModeAdd);
  796. pcontext->DrawLineStrip(pvertex, vcount);
  797. }
  798. };
  799. TRef<Geo> CreateBoltGeo(VectorValue* pstart, VectorValue* pend, float size, Surface* psurface)
  800. {
  801. return new BoltGeo(pstart, pend, size, psurface);
  802. }
  803. //////////////////////////////////////////////////////////////////////////////
  804. //
  805. // CullGeo
  806. //
  807. //////////////////////////////////////////////////////////////////////////////
  808. class CullGeo : public WrapGeo {
  809. private:
  810. float m_radius;
  811. public:
  812. CullGeo(Geo* pgeo) :
  813. WrapGeo(pgeo)
  814. {
  815. m_radius = GetGeo()->GetRadius(Matrix::GetIdentity());
  816. }
  817. void Render(Context* pcontext)
  818. {
  819. bool bNoClipping;
  820. if (!pcontext->IsCulled(Vector::GetZero(), m_radius, bNoClipping)) {
  821. if (bNoClipping) {
  822. pcontext->SetClipping(false);
  823. }
  824. //float screenRadius = pcontext->GetScreenRadius(Vector::GetZero(), m_radius);
  825. //pcontext->SetLOD(screenRadius * max(m_lodBiasMin, s_lodBias));
  826. GetGeo()->Render(pcontext);
  827. if (bNoClipping) {
  828. pcontext->SetClipping(true);
  829. }
  830. }
  831. }
  832. };
  833. TRef<Geo> CreateCullGeo(Geo* pgeo)
  834. {
  835. return new CullGeo(pgeo);
  836. }
  837. //////////////////////////////////////////////////////////////////////////////
  838. //
  839. // CopyModeGeo
  840. //
  841. //////////////////////////////////////////////////////////////////////////////
  842. class CopyModeGeo : public WrapGeo {
  843. public:
  844. CopyModeGeo(Geo* pgeo) :
  845. WrapGeo(pgeo)
  846. {
  847. }
  848. void Render(Context* pcontext)
  849. {
  850. #ifdef FixPermedia
  851. pcontext->SetShadeMode(ShadeModeGlobalColor);
  852. pcontext->SetColor(Color::White());
  853. #else
  854. pcontext->SetShadeMode(ShadeModeCopy);
  855. #endif
  856. GetGeo()->Render(pcontext);
  857. }
  858. };
  859. TRef<Geo> CreateCopyModeGeo(Geo* pgeo)
  860. {
  861. return new CopyModeGeo(pgeo);
  862. }