Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Emitter.cpp 6.1KB

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