Open Source Tomb Raider Engine
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

Emitter.cpp 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*!
  2. * \file src/Emitter.cpp
  3. * \brief Particle emitter class.
  4. *
  5. * \author Mongoose
  6. */
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #ifdef __APPLE__
  11. #include <OpenGL/gl.h>
  12. #else
  13. #include <GL/gl.h>
  14. #endif
  15. #include "Emitter.h"
  16. vec_t Emitter::mFrustum[6][4];
  17. int Emitter::compareParticleDist(const void *voidA, const void *voidB) {
  18. Particle *a = const_cast<Particle *>(static_cast<const Particle *>(voidA));
  19. Particle *b = const_cast<Particle *>(static_cast<const Particle *>(voidB));
  20. float x, y, z, distA, distB;
  21. if (!a || !b)
  22. return -1; // error really
  23. a->Pos(&x, &y, &z);
  24. distA = (Emitter::mFrustum[5][0] * x +
  25. Emitter::mFrustum[5][1] * y +
  26. Emitter::mFrustum[5][2] * z +
  27. Emitter::mFrustum[5][3]);
  28. b->Pos(&x, &y, &z);
  29. distB = (Emitter::mFrustum[5][0] * x +
  30. Emitter::mFrustum[5][1] * y +
  31. Emitter::mFrustum[5][2] * z +
  32. Emitter::mFrustum[5][3]);
  33. // reverse less/greater than
  34. // less than
  35. if (distA > distB)
  36. return -1;
  37. // greater than ( no need for equal )
  38. return 1;
  39. }
  40. Emitter::Emitter(const char *name, int n) {
  41. _name = NULL;
  42. _flags = 0;
  43. _particle = NULL;
  44. _count = 0;
  45. _pos[0] = _pos[1] = _pos[2] = 0.0;
  46. _mangle[0] = _mangle[1] = _mangle[2] = 0.0;
  47. Name(name);
  48. ParticleArray(n);
  49. }
  50. Emitter::~Emitter() {
  51. if (_name)
  52. delete [] _name;
  53. if (_particle)
  54. delete [] _particle;
  55. _count = 0;
  56. }
  57. Particle *Emitter::Particles() {
  58. return _particle;
  59. }
  60. int Emitter::Count() {
  61. return _count;
  62. }
  63. void Emitter::Pos(float *x, float *y, float *z) {
  64. *x = _pos[0];
  65. *y = _pos[1];
  66. *z = _pos[2];
  67. }
  68. void Emitter::Pos(float x, float y, float z) {
  69. _pos[0] = x;
  70. _pos[1] = y;
  71. _pos[2] = z;
  72. }
  73. void Emitter::Orientation(float *x, float *y, float *z) {
  74. *x = _mangle[0];
  75. *y = _mangle[1];
  76. *z = _mangle[2];
  77. }
  78. void Emitter::Orientation(float x, float y, float z) {
  79. _mangle[0] = x;
  80. _mangle[1] = y;
  81. _mangle[2] = z;
  82. }
  83. unsigned int Emitter::Flags() {
  84. return _flags;
  85. }
  86. void Emitter::Flags(unsigned int flag, bool op) {
  87. _flags |= flag;
  88. if (!op)
  89. _flags ^= flag;
  90. }
  91. void Emitter::ParticleArray(int n) {
  92. if (n) {
  93. if (_particle) {
  94. _count = 0;
  95. delete [] _particle;
  96. }
  97. _count = n;
  98. _particle = new Particle[_count];
  99. }
  100. }
  101. void Emitter::Name(const char *name) {
  102. if (name && name[0]) {
  103. if (_name)
  104. delete [] _name;
  105. int l = strlen(name);
  106. _name = new char[l+1];
  107. // Mongoose 2002.01.09, Mongoose says 'Only you can prevent overflows'
  108. strncpy(_name, name, l);
  109. _name[l] = 0;
  110. }
  111. }
  112. void Emitter::SetTextureId(int id) {
  113. for (unsigned int i = 0; i < _count; i++)
  114. _particle[i].TextureId(id);
  115. }
  116. void Emitter::TextureId(unsigned int particle_start, unsigned int particle_end, int id) {
  117. if ((particle_start < _count) && (particle_end > 0 && particle_end <= _count) && (particle_start < particle_end)) {
  118. for (unsigned int i = particle_start; i < particle_end; i++)
  119. _particle[i].TextureId(id);
  120. }
  121. }
  122. void Emitter::Color(unsigned int particle_start, unsigned int particle_end, float r, float g, float b) {
  123. if ((particle_start < _count) && (particle_end > 0 && particle_end <= _count) && (particle_start < particle_end)) {
  124. for (unsigned int i = particle_start; i < particle_end; i++)
  125. _particle[i].Color(r, g, b);
  126. }
  127. }
  128. void Emitter::Speed(unsigned int particle_start, unsigned int particle_end, float x, float y, float z) {
  129. if ((particle_start < _count) && (particle_end > 0 && particle_end <= _count) && (particle_start < particle_end)) {
  130. for (unsigned int i = particle_start; i < particle_end; i++)
  131. _particle[i].Speed(x, y, z);
  132. }
  133. }
  134. void Emitter::Force(unsigned int particle_start, unsigned int particle_end, float x, float y, float z) {
  135. if ((particle_start < _count) && (particle_end > 0 && particle_end <= _count) && (particle_start < particle_end)) {
  136. for (unsigned int i = particle_start; i < particle_end; i++)
  137. _particle[i].Force(x, y, z);
  138. }
  139. }
  140. void Emitter::Draw() {
  141. unsigned int i, p;
  142. float x, y, z;
  143. float r, g, b;
  144. float life;
  145. if (!_count || !_particle) {
  146. printf("Emitter::Draw> No particles!\n");
  147. return;
  148. }
  149. glPushMatrix();
  150. //glRotatef(_mangle[0], 1.0, 0.0, 0.0);
  151. //glRotatef(_mangle[1], 0.0, 1.0, 0.0);
  152. //glRotatef(_mangle[2], 0.0, 0.0, 1.0);
  153. //glTranslatef(_pos[0], _pos[1], _pos[2]);
  154. if (_flags & fUseDepthSorting)
  155. qsort(_particle, _count, sizeof(Particle), compareParticleDist);
  156. for (i = 0; i < _count; i++) {
  157. if (_particle[i].isActive()) {
  158. _particle[i].Pos(&x, &y, &z);
  159. if (_flags & fUseFrustumCulling) {
  160. for (p = 0; p < 6; ++p) {
  161. if (((mFrustum[p][0] * x) + (mFrustum[p][1] * y) + (mFrustum[p][2] * z) + mFrustum[p][3]) < 0) {
  162. _particle[i].setActive(false);
  163. break;
  164. }
  165. }
  166. if (!_particle[i].isActive())
  167. continue;
  168. }
  169. _particle[i].Color(&r, &g, &b);
  170. life = _particle[i].Life();
  171. // Mongoose 2002.01.01, Removed Texture agent dep
  172. glBindTexture(GL_TEXTURE_2D, _particle[i].Texture());
  173. // Alpha is determined by life, which is affected by blend amount
  174. glColor4f(r, g, b, life);
  175. // Render tristrip quad
  176. glBegin(GL_TRIANGLE_STRIP);
  177. glTexCoord2d(1.0, 1.0);
  178. glVertex3f(x + 0.5f, y + 0.5f, z);
  179. glTexCoord2d(0.0, 1.0);
  180. glVertex3f(x - 0.5f, y + 0.5f, z);
  181. glTexCoord2d(1.0, 0.0);
  182. glVertex3f(x + 0.5f, y - 0.5f, z);
  183. glTexCoord2d(0.0, 0.0);
  184. glVertex3f(x - 0.5f, y - 0.5f, z);
  185. glEnd();
  186. // Update particle's attributes for it's life cycle
  187. _particle[i].Update();
  188. }
  189. }
  190. glPopMatrix();
  191. }