particleSystemComponent.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { Mesh } from "../Meshes/mesh";
  2. import { IParticleSystem } from "./IParticleSystem";
  3. import { GPUParticleSystem } from "./gpuParticleSystem";
  4. import { AbstractScene } from "../abstractScene";
  5. import { Effect } from "../Materials/effect";
  6. import { Engine } from "../Engines/engine";
  7. import { ParticleSystem } from "./particleSystem";
  8. import { Scene } from "../scene";
  9. import { SceneComponentConstants } from "../sceneComponent";
  10. import { AssetContainer } from "../assetContainer";
  11. import "../Shaders/particles.vertex";
  12. import { EffectFallbacks } from '../Materials/effectFallbacks';
  13. // Adds the parsers to the scene parsers.
  14. AbstractScene.AddParser(SceneComponentConstants.NAME_PARTICLESYSTEM, (parsedData: any, scene: Scene, container: AssetContainer, rootUrl: string) => {
  15. let individualParser = AbstractScene.GetIndividualParser(SceneComponentConstants.NAME_PARTICLESYSTEM);
  16. if (!individualParser) {
  17. return;
  18. }
  19. // Particles Systems
  20. if (parsedData.particleSystems !== undefined && parsedData.particleSystems !== null) {
  21. for (var index = 0, cache = parsedData.particleSystems.length; index < cache; index++) {
  22. var parsedParticleSystem = parsedData.particleSystems[index];
  23. container.particleSystems.push(individualParser(parsedParticleSystem, scene, rootUrl));
  24. }
  25. }
  26. });
  27. AbstractScene.AddIndividualParser(SceneComponentConstants.NAME_PARTICLESYSTEM, (parsedParticleSystem: any, scene: Scene, rootUrl: string) => {
  28. if (parsedParticleSystem.activeParticleCount) {
  29. let ps = GPUParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
  30. return ps;
  31. } else {
  32. let ps = ParticleSystem.Parse(parsedParticleSystem, scene, rootUrl);
  33. return ps;
  34. }
  35. });
  36. declare module "../Engines/engine" {
  37. export interface Engine {
  38. /**
  39. * Create an effect to use with particle systems.
  40. * Please note that some parameters like animation sheets or not being billboard are not supported in this configuration, except if you pass
  41. * the particle system for which you want to create a custom effect in the last parameter
  42. * @param fragmentName defines the base name of the effect (The name of file without .fragment.fx)
  43. * @param uniformsNames defines a list of attribute names
  44. * @param samplers defines an array of string used to represent textures
  45. * @param defines defines the string containing the defines to use to compile the shaders
  46. * @param fallbacks defines the list of potential fallbacks to use if shader conmpilation fails
  47. * @param onCompiled defines a function to call when the effect creation is successful
  48. * @param onError defines a function to call when the effect creation has failed
  49. * @param particleSystem the particle system you want to create the effect for
  50. * @returns the new Effect
  51. */
  52. createEffectForParticles(fragmentName: string, uniformsNames: string[], samplers: string[], defines: string, fallbacks?: EffectFallbacks,
  53. onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void, particleSystem?: IParticleSystem): Effect;
  54. }
  55. }
  56. Engine.prototype.createEffectForParticles = function(fragmentName: string, uniformsNames: string[] = [], samplers: string[] = [], defines = "", fallbacks?: EffectFallbacks,
  57. onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void, particleSystem?: IParticleSystem): Effect {
  58. var attributesNamesOrOptions: Array<string> = [];
  59. var effectCreationOption: Array<string> = [];
  60. var allSamplers: Array<string> = [];
  61. if (particleSystem) {
  62. particleSystem.fillUniformsAttributesAndSamplerNames(effectCreationOption, attributesNamesOrOptions, allSamplers);
  63. } else {
  64. attributesNamesOrOptions = ParticleSystem._GetAttributeNamesOrOptions();
  65. effectCreationOption = ParticleSystem._GetEffectCreationOptions();
  66. }
  67. if (defines.indexOf(" BILLBOARD") === -1) {
  68. defines += "\n#define BILLBOARD\n";
  69. }
  70. if (samplers.indexOf("diffuseSampler") === -1) {
  71. samplers.push("diffuseSampler");
  72. }
  73. return this.createEffect(
  74. {
  75. vertex: particleSystem?.vertexShaderName ?? "particles",
  76. fragmentElement: fragmentName
  77. },
  78. attributesNamesOrOptions,
  79. effectCreationOption.concat(uniformsNames),
  80. allSamplers.concat(samplers), defines, fallbacks, onCompiled, onError);
  81. };
  82. declare module "../Meshes/mesh" {
  83. export interface Mesh {
  84. /**
  85. * Returns an array populated with IParticleSystem objects whose the mesh is the emitter
  86. * @returns an array of IParticleSystem
  87. */
  88. getEmittedParticleSystems(): IParticleSystem[];
  89. /**
  90. * Returns an array populated with IParticleSystem objects whose the mesh or its children are the emitter
  91. * @returns an array of IParticleSystem
  92. */
  93. getHierarchyEmittedParticleSystems(): IParticleSystem[];
  94. }
  95. }
  96. Mesh.prototype.getEmittedParticleSystems = function(): IParticleSystem[] {
  97. var results = new Array<IParticleSystem>();
  98. for (var index = 0; index < this.getScene().particleSystems.length; index++) {
  99. var particleSystem = this.getScene().particleSystems[index];
  100. if (particleSystem.emitter === this) {
  101. results.push(particleSystem);
  102. }
  103. }
  104. return results;
  105. };
  106. Mesh.prototype.getHierarchyEmittedParticleSystems = function(): IParticleSystem[] {
  107. var results = new Array<IParticleSystem>();
  108. var descendants = this.getDescendants();
  109. descendants.push(this);
  110. for (var index = 0; index < this.getScene().particleSystems.length; index++) {
  111. var particleSystem = this.getScene().particleSystems[index];
  112. let emitter: any = particleSystem.emitter;
  113. if (emitter.position && descendants.indexOf(emitter) !== -1) {
  114. results.push(particleSystem);
  115. }
  116. }
  117. return results;
  118. };