babylon.particle.ts 11 KB

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