particle.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import { Vector2, Vector3, TmpVectors, Vector4 } from "../Maths/math.vector.js";
  2. import { Color4 } from "../Maths/math.color.js";
  3. import { Clamp } from "../Maths/math.scalar.functions.js";
  4. /**
  5. * A particle represents one of the element emitted by a particle system.
  6. * This is mainly define by its coordinates, direction, velocity and age.
  7. */
  8. export class Particle {
  9. /**
  10. * Creates a new instance Particle
  11. * @param particleSystem the particle system the particle belongs to
  12. */
  13. constructor(
  14. /**
  15. * The particle system the particle belongs to.
  16. */
  17. particleSystem) {
  18. this.particleSystem = particleSystem;
  19. /**
  20. * The world position of the particle in the scene.
  21. */
  22. this.position = Vector3.Zero();
  23. /**
  24. * The world direction of the particle in the scene.
  25. */
  26. this.direction = Vector3.Zero();
  27. /**
  28. * The color of the particle.
  29. */
  30. this.color = new Color4(0, 0, 0, 0);
  31. /**
  32. * The color change of the particle per step.
  33. */
  34. this.colorStep = new Color4(0, 0, 0, 0);
  35. /**
  36. * Defines how long will the life of the particle be.
  37. */
  38. this.lifeTime = 1.0;
  39. /**
  40. * The current age of the particle.
  41. */
  42. this.age = 0;
  43. /**
  44. * The current size of the particle.
  45. */
  46. this.size = 0;
  47. /**
  48. * The current scale of the particle.
  49. */
  50. this.scale = new Vector2(1, 1);
  51. /**
  52. * The current angle of the particle.
  53. */
  54. this.angle = 0;
  55. /**
  56. * Defines how fast is the angle changing.
  57. */
  58. this.angularSpeed = 0;
  59. /**
  60. * Defines the cell index used by the particle to be rendered from a sprite.
  61. */
  62. this.cellIndex = 0;
  63. /** @internal */
  64. this._attachedSubEmitters = null;
  65. /** @internal */
  66. this._currentColor1 = new Color4(0, 0, 0, 0);
  67. /** @internal */
  68. this._currentColor2 = new Color4(0, 0, 0, 0);
  69. /** @internal */
  70. this._currentSize1 = 0;
  71. /** @internal */
  72. this._currentSize2 = 0;
  73. /** @internal */
  74. this._currentAngularSpeed1 = 0;
  75. /** @internal */
  76. this._currentAngularSpeed2 = 0;
  77. /** @internal */
  78. this._currentVelocity1 = 0;
  79. /** @internal */
  80. this._currentVelocity2 = 0;
  81. /** @internal */
  82. this._currentLimitVelocity1 = 0;
  83. /** @internal */
  84. this._currentLimitVelocity2 = 0;
  85. /** @internal */
  86. this._currentDrag1 = 0;
  87. /** @internal */
  88. this._currentDrag2 = 0;
  89. this.id = Particle._Count++;
  90. if (!this.particleSystem.isAnimationSheetEnabled) {
  91. return;
  92. }
  93. this._updateCellInfoFromSystem();
  94. }
  95. _updateCellInfoFromSystem() {
  96. this.cellIndex = this.particleSystem.startSpriteCellID;
  97. }
  98. /**
  99. * Defines how the sprite cell index is updated for the particle
  100. */
  101. updateCellIndex() {
  102. let offsetAge = this.age;
  103. let changeSpeed = this.particleSystem.spriteCellChangeSpeed;
  104. if (this.particleSystem.spriteRandomStartCell) {
  105. if (this._randomCellOffset === undefined) {
  106. this._randomCellOffset = Math.random() * this.lifeTime;
  107. }
  108. if (changeSpeed === 0) {
  109. // Special case when speed = 0 meaning we want to stay on initial cell
  110. changeSpeed = 1;
  111. offsetAge = this._randomCellOffset;
  112. }
  113. else {
  114. offsetAge += this._randomCellOffset;
  115. }
  116. }
  117. const dist = this._initialEndSpriteCellID - this._initialStartSpriteCellID + 1;
  118. let ratio;
  119. if (this._initialSpriteCellLoop) {
  120. ratio = Clamp(((offsetAge * changeSpeed) % this.lifeTime) / this.lifeTime);
  121. }
  122. else {
  123. ratio = Clamp((offsetAge * changeSpeed) / this.lifeTime);
  124. }
  125. this.cellIndex = (this._initialStartSpriteCellID + ratio * dist) | 0;
  126. }
  127. /**
  128. * @internal
  129. */
  130. _inheritParticleInfoToSubEmitter(subEmitter) {
  131. if (subEmitter.particleSystem.emitter.position) {
  132. const emitterMesh = subEmitter.particleSystem.emitter;
  133. emitterMesh.position.copyFrom(this.position);
  134. if (subEmitter.inheritDirection) {
  135. const temp = TmpVectors.Vector3[0];
  136. this.direction.normalizeToRef(temp);
  137. emitterMesh.setDirection(temp, 0, Math.PI / 2);
  138. }
  139. }
  140. else {
  141. const emitterPosition = subEmitter.particleSystem.emitter;
  142. emitterPosition.copyFrom(this.position);
  143. }
  144. // Set inheritedVelocityOffset to be used when new particles are created
  145. this.direction.scaleToRef(subEmitter.inheritedVelocityAmount / 2, TmpVectors.Vector3[0]);
  146. subEmitter.particleSystem._inheritedVelocityOffset.copyFrom(TmpVectors.Vector3[0]);
  147. }
  148. /** @internal */
  149. _inheritParticleInfoToSubEmitters() {
  150. if (this._attachedSubEmitters && this._attachedSubEmitters.length > 0) {
  151. this._attachedSubEmitters.forEach((subEmitter) => {
  152. this._inheritParticleInfoToSubEmitter(subEmitter);
  153. });
  154. }
  155. }
  156. /** @internal */
  157. _reset() {
  158. this.age = 0;
  159. this.id = Particle._Count++;
  160. this._currentColorGradient = null;
  161. this._currentSizeGradient = null;
  162. this._currentAngularSpeedGradient = null;
  163. this._currentVelocityGradient = null;
  164. this._currentLimitVelocityGradient = null;
  165. this._currentDragGradient = null;
  166. this.cellIndex = this.particleSystem.startSpriteCellID;
  167. this._randomCellOffset = undefined;
  168. }
  169. /**
  170. * Copy the properties of particle to another one.
  171. * @param other the particle to copy the information to.
  172. */
  173. copyTo(other) {
  174. other.position.copyFrom(this.position);
  175. if (this._initialDirection) {
  176. if (other._initialDirection) {
  177. other._initialDirection.copyFrom(this._initialDirection);
  178. }
  179. else {
  180. other._initialDirection = this._initialDirection.clone();
  181. }
  182. }
  183. else {
  184. other._initialDirection = null;
  185. }
  186. other.direction.copyFrom(this.direction);
  187. if (this._localPosition) {
  188. if (other._localPosition) {
  189. other._localPosition.copyFrom(this._localPosition);
  190. }
  191. else {
  192. other._localPosition = this._localPosition.clone();
  193. }
  194. }
  195. other.color.copyFrom(this.color);
  196. other.colorStep.copyFrom(this.colorStep);
  197. other.lifeTime = this.lifeTime;
  198. other.age = this.age;
  199. other._randomCellOffset = this._randomCellOffset;
  200. other.size = this.size;
  201. other.scale.copyFrom(this.scale);
  202. other.angle = this.angle;
  203. other.angularSpeed = this.angularSpeed;
  204. other.particleSystem = this.particleSystem;
  205. other.cellIndex = this.cellIndex;
  206. other.id = this.id;
  207. other._attachedSubEmitters = this._attachedSubEmitters;
  208. if (this._currentColorGradient) {
  209. other._currentColorGradient = this._currentColorGradient;
  210. other._currentColor1.copyFrom(this._currentColor1);
  211. other._currentColor2.copyFrom(this._currentColor2);
  212. }
  213. if (this._currentSizeGradient) {
  214. other._currentSizeGradient = this._currentSizeGradient;
  215. other._currentSize1 = this._currentSize1;
  216. other._currentSize2 = this._currentSize2;
  217. }
  218. if (this._currentAngularSpeedGradient) {
  219. other._currentAngularSpeedGradient = this._currentAngularSpeedGradient;
  220. other._currentAngularSpeed1 = this._currentAngularSpeed1;
  221. other._currentAngularSpeed2 = this._currentAngularSpeed2;
  222. }
  223. if (this._currentVelocityGradient) {
  224. other._currentVelocityGradient = this._currentVelocityGradient;
  225. other._currentVelocity1 = this._currentVelocity1;
  226. other._currentVelocity2 = this._currentVelocity2;
  227. }
  228. if (this._currentLimitVelocityGradient) {
  229. other._currentLimitVelocityGradient = this._currentLimitVelocityGradient;
  230. other._currentLimitVelocity1 = this._currentLimitVelocity1;
  231. other._currentLimitVelocity2 = this._currentLimitVelocity2;
  232. }
  233. if (this._currentDragGradient) {
  234. other._currentDragGradient = this._currentDragGradient;
  235. other._currentDrag1 = this._currentDrag1;
  236. other._currentDrag2 = this._currentDrag2;
  237. }
  238. if (this.particleSystem.isAnimationSheetEnabled) {
  239. other._initialStartSpriteCellID = this._initialStartSpriteCellID;
  240. other._initialEndSpriteCellID = this._initialEndSpriteCellID;
  241. other._initialSpriteCellLoop = this._initialSpriteCellLoop;
  242. }
  243. if (this.particleSystem.useRampGradients) {
  244. if (other.remapData && this.remapData) {
  245. other.remapData.copyFrom(this.remapData);
  246. }
  247. else {
  248. other.remapData = new Vector4(0, 0, 0, 0);
  249. }
  250. }
  251. if (this._randomNoiseCoordinates1) {
  252. if (other._randomNoiseCoordinates1) {
  253. other._randomNoiseCoordinates1.copyFrom(this._randomNoiseCoordinates1);
  254. other._randomNoiseCoordinates2.copyFrom(this._randomNoiseCoordinates2);
  255. }
  256. else {
  257. other._randomNoiseCoordinates1 = this._randomNoiseCoordinates1.clone();
  258. other._randomNoiseCoordinates2 = this._randomNoiseCoordinates2.clone();
  259. }
  260. }
  261. }
  262. }
  263. Particle._Count = 0;
  264. //# sourceMappingURL=particle.js.map