Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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. }