Open Source Tomb Raider Engine
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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