sphereParticleEmitter.ts 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import { Vector3, Matrix } from "../../Maths/math.vector";
  2. import { Scalar } from "../../Maths/math.scalar";
  3. import { Effect } from "../../Materials/effect";
  4. import { Particle } from "../../Particles/particle";
  5. import { IParticleEmitterType } from "./IParticleEmitterType";
  6. import { DeepCopier } from "../../Misc/deepCopier";
  7. /**
  8. * Particle emitter emitting particles from the inside of a sphere.
  9. * It emits the particles alongside the sphere radius. The emission direction might be randomized.
  10. */
  11. export class SphereParticleEmitter implements IParticleEmitterType {
  12. /**
  13. * Creates a new instance SphereParticleEmitter
  14. * @param radius the radius of the emission sphere (1 by default)
  15. * @param radiusRange the range of the emission sphere [0-1] 0 Surface only, 1 Entire Radius (1 by default)
  16. * @param directionRandomizer defines how much to randomize the particle direction [0-1]
  17. */
  18. constructor(
  19. /**
  20. * The radius of the emission sphere.
  21. */
  22. public radius = 1,
  23. /**
  24. * The range of emission [0-1] 0 Surface only, 1 Entire Radius.
  25. */
  26. public radiusRange = 1,
  27. /**
  28. * How much to randomize the particle direction [0-1].
  29. */
  30. public directionRandomizer = 0) {
  31. }
  32. /**
  33. * Called by the particle System when the direction is computed for the created particle.
  34. * @param worldMatrix is the world matrix of the particle system
  35. * @param directionToUpdate is the direction vector to update with the result
  36. * @param particle is the particle we are computed the direction for
  37. * @param isLocal defines if the direction should be set in local space
  38. */
  39. public startDirectionFunction(worldMatrix: Matrix, directionToUpdate: Vector3, particle: Particle, isLocal: boolean): void {
  40. var direction = particle.position.subtract(worldMatrix.getTranslation()).normalize();
  41. var randX = Scalar.RandomRange(0, this.directionRandomizer);
  42. var randY = Scalar.RandomRange(0, this.directionRandomizer);
  43. var randZ = Scalar.RandomRange(0, this.directionRandomizer);
  44. direction.x += randX;
  45. direction.y += randY;
  46. direction.z += randZ;
  47. direction.normalize();
  48. if (isLocal) {
  49. directionToUpdate.copyFrom(direction);
  50. return;
  51. }
  52. Vector3.TransformNormalFromFloatsToRef(direction.x, direction.y, direction.z, worldMatrix, directionToUpdate);
  53. }
  54. /**
  55. * Called by the particle System when the position is computed for the created particle.
  56. * @param worldMatrix is the world matrix of the particle system
  57. * @param positionToUpdate is the position vector to update with the result
  58. * @param particle is the particle we are computed the position for
  59. * @param isLocal defines if the position should be set in local space
  60. */
  61. public startPositionFunction(worldMatrix: Matrix, positionToUpdate: Vector3, particle: Particle, isLocal: boolean): void {
  62. var randRadius = this.radius - Scalar.RandomRange(0, this.radius * this.radiusRange);
  63. var v = Scalar.RandomRange(0, 1.0);
  64. var phi = Scalar.RandomRange(0, 2 * Math.PI);
  65. var theta = Math.acos(2 * v - 1);
  66. var randX = randRadius * Math.cos(phi) * Math.sin(theta);
  67. var randY = randRadius * Math.cos(theta);
  68. var randZ = randRadius * Math.sin(phi) * Math.sin(theta);
  69. if (isLocal) {
  70. positionToUpdate.copyFromFloats(randX, randY, randZ);
  71. return;
  72. }
  73. Vector3.TransformCoordinatesFromFloatsToRef(randX, randY, randZ, worldMatrix, positionToUpdate);
  74. }
  75. /**
  76. * Clones the current emitter and returns a copy of it
  77. * @returns the new emitter
  78. */
  79. public clone(): SphereParticleEmitter {
  80. let newOne = new SphereParticleEmitter(this.radius, this.directionRandomizer);
  81. DeepCopier.DeepCopy(this, newOne);
  82. return newOne;
  83. }
  84. /**
  85. * Called by the GPUParticleSystem to setup the update shader
  86. * @param effect defines the update shader
  87. */
  88. public applyToShader(effect: Effect): void {
  89. effect.setFloat("radius", this.radius);
  90. effect.setFloat("radiusRange", this.radiusRange);
  91. effect.setFloat("directionRandomizer", this.directionRandomizer);
  92. }
  93. /**
  94. * Returns a string to use to update the GPU particles update shader
  95. * @returns a string containng the defines string
  96. */
  97. public getEffectDefines(): string {
  98. return "#define SPHEREEMITTER";
  99. }
  100. /**
  101. * Returns the string "SphereParticleEmitter"
  102. * @returns a string containing the class name
  103. */
  104. public getClassName(): string {
  105. return "SphereParticleEmitter";
  106. }
  107. /**
  108. * Serializes the particle system to a JSON object.
  109. * @returns the JSON object
  110. */
  111. public serialize(): any {
  112. var serializationObject: any = {};
  113. serializationObject.type = this.getClassName();
  114. serializationObject.radius = this.radius;
  115. serializationObject.radiusRange = this.radiusRange;
  116. serializationObject.directionRandomizer = this.directionRandomizer;
  117. return serializationObject;
  118. }
  119. /**
  120. * Parse properties from a JSON object
  121. * @param serializationObject defines the JSON object
  122. */
  123. public parse(serializationObject: any): void {
  124. this.radius = serializationObject.radius;
  125. this.radiusRange = serializationObject.radiusRange;
  126. this.directionRandomizer = serializationObject.directionRandomizer;
  127. }
  128. }
  129. /**
  130. * Particle emitter emitting particles from the inside of a sphere.
  131. * It emits the particles randomly between two vectors.
  132. */
  133. export class SphereDirectedParticleEmitter extends SphereParticleEmitter {
  134. /**
  135. * Creates a new instance SphereDirectedParticleEmitter
  136. * @param radius the radius of the emission sphere (1 by default)
  137. * @param direction1 the min limit of the emission direction (up vector by default)
  138. * @param direction2 the max limit of the emission direction (up vector by default)
  139. */
  140. constructor(radius = 1,
  141. /**
  142. * The min limit of the emission direction.
  143. */
  144. public direction1 = new Vector3(0, 1, 0),
  145. /**
  146. * The max limit of the emission direction.
  147. */
  148. public direction2 = new Vector3(0, 1, 0)) {
  149. super(radius);
  150. }
  151. /**
  152. * Called by the particle System when the direction is computed for the created particle.
  153. * @param worldMatrix is the world matrix of the particle system
  154. * @param directionToUpdate is the direction vector to update with the result
  155. * @param particle is the particle we are computed the direction for
  156. */
  157. public startDirectionFunction(worldMatrix: Matrix, directionToUpdate: Vector3, particle: Particle): void {
  158. var randX = Scalar.RandomRange(this.direction1.x, this.direction2.x);
  159. var randY = Scalar.RandomRange(this.direction1.y, this.direction2.y);
  160. var randZ = Scalar.RandomRange(this.direction1.z, this.direction2.z);
  161. Vector3.TransformNormalFromFloatsToRef(randX, randY, randZ, worldMatrix, directionToUpdate);
  162. }
  163. /**
  164. * Clones the current emitter and returns a copy of it
  165. * @returns the new emitter
  166. */
  167. public clone(): SphereDirectedParticleEmitter {
  168. let newOne = new SphereDirectedParticleEmitter(this.radius, this.direction1, this.direction2);
  169. DeepCopier.DeepCopy(this, newOne);
  170. return newOne;
  171. }
  172. /**
  173. * Called by the GPUParticleSystem to setup the update shader
  174. * @param effect defines the update shader
  175. */
  176. public applyToShader(effect: Effect): void {
  177. effect.setFloat("radius", this.radius);
  178. effect.setFloat("radiusRange", this.radiusRange);
  179. effect.setVector3("direction1", this.direction1);
  180. effect.setVector3("direction2", this.direction2);
  181. }
  182. /**
  183. * Returns a string to use to update the GPU particles update shader
  184. * @returns a string containng the defines string
  185. */
  186. public getEffectDefines(): string {
  187. return "#define SPHEREEMITTER\n#define DIRECTEDSPHEREEMITTER";
  188. }
  189. /**
  190. * Returns the string "SphereDirectedParticleEmitter"
  191. * @returns a string containing the class name
  192. */
  193. public getClassName(): string {
  194. return "SphereDirectedParticleEmitter";
  195. }
  196. /**
  197. * Serializes the particle system to a JSON object.
  198. * @returns the JSON object
  199. */
  200. public serialize(): any {
  201. var serializationObject = super.serialize();
  202. serializationObject.direction1 = this.direction1.asArray();
  203. serializationObject.direction2 = this.direction2.asArray();
  204. return serializationObject;
  205. }
  206. /**
  207. * Parse properties from a JSON object
  208. * @param serializationObject defines the JSON object
  209. */
  210. public parse(serializationObject: any): void {
  211. super.parse(serializationObject);
  212. this.direction1.copyFrom(serializationObject.direction1);
  213. this.direction2.copyFrom(serializationObject.direction2);
  214. }
  215. }