PageRenderTime 48ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/AEmitter.cpp

https://gitlab.com/ayufan/ayuine2b
C++ | 264 lines | 149 code | 54 blank | 61 comment | 12 complexity | 133426755533d3ff520a0241098c5253 MD5 | raw file
  1. //------------------------------------//
  2. //
  3. // AEmitter.cpp
  4. //
  5. // Author: ayufan (ayufan[at]o2.pl)
  6. // Project: ayuine2
  7. // Date: 2006-8-18
  8. //
  9. //------------------------------------//
  10. #include "StdAfx.hpp"
  11. namespace ayuine
  12. {
  13. //------------------------------------//
  14. // ParticleVertex: Static Fields
  15. VertexDeclElement ParticleVertex::Decl[] = {
  16. {0, OffsetOf(ParticleVertex, Origin), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
  17. {0, OffsetOf(ParticleVertex, Coords), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
  18. {0, OffsetOf(ParticleVertex, Color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
  19. D3DDECL_END()
  20. };
  21. //------------------------------------//
  22. // AEmitter: Constructor
  23. AEmitter::AEmitter(u32 particles) {
  24. // Flags
  25. Flags = afUpdate | afZones | afArea | afPrepare | afTransform;
  26. // Ustaw domyœlne parametry
  27. _active = _free = nullptr;
  28. _time = _last = 0;
  29. Type = etPoint;
  30. Enabled = true;
  31. World = false;
  32. Mass = 1.0f;
  33. LifeTime = 1.0f;
  34. Radius = 1.0f;
  35. RadiusDerivative = 0.0f;
  36. StartColor = vec4(1, 1, 1, 1);
  37. EndColor = vec4(0, 0, 0, 0);
  38. Force = vec3(0, 0, 1);
  39. StartVelocity = 1.0f;
  40. MaxVelocity = 1.0f;
  41. MaxAngular = 1.0f;
  42. // Utwórz wszystkie czšsteczki
  43. _particles.resize(particles);
  44. // Dołšcz do listy pustych
  45. ArrayEach(Particle, i, _particles) {
  46. i->Next = _free;
  47. _free = &*i;
  48. }
  49. // Utwórz format wierzchołków
  50. _vertexType.reset(new VertexType(ParticleVertex::Decl));
  51. }
  52. //------------------------------------//
  53. // AEmitter: Destructor
  54. AEmitter::~AEmitter() {
  55. }
  56. //------------------------------------//
  57. // AEmitter: Methods
  58. void AEmitter::preupdate(f32 dt) {
  59. Particle *curr;
  60. Particle *next;
  61. // Wywołaj nadrzędnš metodę aktualizacji
  62. Actor::preupdate(dt);
  63. // Wyzeruj obszar emittera
  64. Box.clear();
  65. // Czy mamy dodawać nowe czšsteczki?
  66. if(Enabled) {
  67. // Dodaj róznicę czasowš
  68. _time += dt;
  69. // Oblicz co ile mamy robić czšsteczki
  70. f32 every = LifeTime / _particles.size();
  71. // Zrób nowe czšsteczki
  72. if(_free && _last + every < _time) {
  73. vec3 at;
  74. // Ustaw czas emitowania
  75. _last = _time;
  76. // Pobierz nowš czšsteczkę
  77. curr = _free;
  78. _free = _free->Next;
  79. // Zresetuj wszystkie parametry
  80. memset(curr, 0, sizeof(Particle));
  81. // Wylosuj wektor
  82. for(u32 i = 0; i < 3; i++)
  83. at[i] = ((rand() % 256) - 128) / 128.0f;
  84. // Ustaw parametry czšsteczek
  85. switch(Type) {
  86. case etPoint:
  87. curr->Origin = Origin;
  88. break;
  89. case etSphere:
  90. curr->Origin = Origin + Size.length() * at;
  91. break;
  92. case etBox:
  93. curr->Origin = Origin + Size * at;
  94. break;
  95. }
  96. // Ustaw siłę
  97. curr->Angular = angles(curr->Origin - Origin);
  98. curr->Velocity = Force + at.normalize() * StartVelocity;
  99. // Dodaj do aktywnych
  100. curr->Next = _active;
  101. _active = curr;
  102. // Oznacz czšsteczki jako zmienione
  103. Changed |= cfArea;
  104. }
  105. }
  106. // Zapisz listę
  107. curr = _active;
  108. // Zniszcz starš listę
  109. _active = nullptr;
  110. // Uaktualnij czšsteczki
  111. while(curr) {
  112. next = curr->Next;
  113. // Oznacz czšsteczki jako zmienione
  114. Changed |= cfArea;
  115. // Uaktualnij czšsteczkę
  116. curr->Origin += curr->Velocity * dt;
  117. curr->Rotation += curr->Angular * dt;
  118. curr->LifeTime += dt;
  119. // Czy jeszcze żyje?
  120. if(curr->LifeTime > LifeTime) {
  121. // Zabić jš
  122. curr->Next = _free;
  123. _free = curr;
  124. curr = next;
  125. continue;
  126. }
  127. f32 time = clamp(curr->LifeTime / LifeTime);
  128. // Uaktualnij parametry
  129. curr->Radius = Radius + Radius * powf(time, abs(RadiusDerivative)) * (RadiusDerivative > MathErr ? 1 : RadiusDerivative < -MathErr ? -1 : 0);
  130. curr->Color = StartColor * (1.0f - time) + EndColor * time;
  131. // Dodaj czšsteczki do obszaru
  132. Box = Box.merge(bbox(curr->Origin, curr->Radius));
  133. curr->Next = _active;
  134. _active = curr;
  135. curr = next;
  136. }
  137. }
  138. void AEmitter::postupdate(f32 dt) {
  139. // Uaktualnij bufory tylko jak zmienił się stan czšsteczek
  140. _needsToUpdate = Changed;
  141. // Wywołaj nadrzędnš metodę aktualizacji
  142. Actor::postupdate(dt);
  143. }
  144. void AEmitter::prepare(RenderFrame &frame) {
  145. // SprawdŸ typ wyœwietlania
  146. if(frame.Type == rmDepth)
  147. return;
  148. // Czy mamy materiał
  149. if(!Material)
  150. return;
  151. // Czšsteczki do wyœwietlenia
  152. if(!_active)
  153. return;
  154. // Musimy uaktualnić czšsteczki?
  155. if(_needsToUpdate) {
  156. Particle* curr;
  157. u32 i;
  158. // Oblicz iloœć aktywnych czšsteczek
  159. for(curr = _active, i = 0; curr; curr = curr->Next)
  160. i++;
  161. // Zarezerwuj miejsce w buforach
  162. _vertices.resize(i * 4);
  163. _indices.resize(i * 6);
  164. // Wygeneruj każdš czšsteczkę
  165. for(curr = _active, i = 0; curr; curr = curr->Next, i++) {
  166. ParticleVertex *vertex = &_vertices.at(i * 4);
  167. u16 *index = &_indices.at(i * 6);
  168. // Zapisz pozycje
  169. vertex[0].Origin = curr->Origin;
  170. vertex[1].Origin = curr->Origin;
  171. vertex[2].Origin = curr->Origin;
  172. vertex[3].Origin = curr->Origin;
  173. // Zapisz koordynanty
  174. vertex[0].Coords = vec4(0, 0, -curr->Radius, -curr->Radius);
  175. vertex[1].Coords = vec4(0, 1, -curr->Radius, +curr->Radius);
  176. vertex[2].Coords = vec4(1, 1, +curr->Radius, +curr->Radius);
  177. vertex[3].Coords = vec4(1, 0, +curr->Radius, -curr->Radius);
  178. // Zapisz kolor
  179. vertex[0].Color =
  180. vertex[1].Color =
  181. vertex[2].Color =
  182. vertex[2].Color = D3DCOLOR_COLORVALUE(curr->Color.X, curr->Color.Y, curr->Color.Z, curr->Color.W);
  183. // Dodaj indeksy wierzchołków
  184. index[0] = i * 4 + 0;
  185. index[1] = i * 4 + 1;
  186. index[2] = i * 4 + 2;
  187. index[3] = i * 4 + 0;
  188. index[4] = i * 4 + 2;
  189. index[5] = i * 4 + 3;
  190. }
  191. _needsToUpdate = false;
  192. }
  193. RenderDynamic *object = new RenderDynamic();
  194. // Ustaw parametry ogólne
  195. object->Box = Box;
  196. object->Sphere = bsphere(Box.center(), Box.radius());
  197. object->Material = Material;
  198. object->Plane = vec4(-frame.CameraAt, Origin);
  199. // Ustaw parametry obiektu
  200. object->VertexType = _vertexType;
  201. object->Vertices = &_vertices.at(0);
  202. object->VertexStride = sizeof(ParticleVertex);
  203. object->VertexCount = _vertices.size();
  204. object->Indices = &_indices.at(0);
  205. object->IndexCount = _indices.size();
  206. object->Drawers.push(BatchIndexedDrawer(D3DPT_TRIANGLELIST, 0, _vertices.size(), 0, _indices.size() / 3));
  207. // Dodaj do renderingu
  208. frame.addFrag(object);
  209. }
  210. };