hemisphericParticleEmitter.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { DeepCopier } from "../../Misc/deepCopier";
  2. import { Vector3, Matrix } from "../../Maths/math.vector";
  3. import { Scalar } from "../../Maths/math.scalar";
  4. import { Effect } from "../../Materials/effect";
  5. import { Particle } from "../../Particles/particle";
  6. import { IParticleEmitterType } from "./IParticleEmitterType";
  7. /**
  8. * Particle emitter emitting particles from the inside of a hemisphere.
  9. * It emits the particles alongside the hemisphere radius. The emission direction might be randomized.
  10. */
  11. export class HemisphericParticleEmitter implements IParticleEmitterType {
  12. /**
  13. * Creates a new instance HemisphericParticleEmitter
  14. * @param radius the radius of the emission hemisphere (1 by default)
  15. * @param radiusRange the range of the emission hemisphere [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 hemisphere.
  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, Math.abs(randY), randZ);
  71. return;
  72. }
  73. Vector3.TransformCoordinatesFromFloatsToRef(randX, Math.abs(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(): HemisphericParticleEmitter {
  80. let newOne = new HemisphericParticleEmitter(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 containing the defines string
  96. */
  97. public getEffectDefines(): string {
  98. return "#define HEMISPHERICEMITTER";
  99. }
  100. /**
  101. * Returns the string "HemisphericParticleEmitter"
  102. * @returns a string containing the class name
  103. */
  104. public getClassName(): string {
  105. return "HemisphericParticleEmitter";
  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. }