Particle system

Make writing a habit together! This is the fourth day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

Particle system: this paper lists some common scenes such as: snowy day, rainy day, firefly, starry sky, smoke, explosion, flame, cloudy, haze - Point particle - custom shader - map - motion animation and particle survival time through the point particle carrying map with custom coloring equipment quality, control particle movement track and survival time, during the survival time control particle transparency and position and color, size, etcCopy the code

Effect of particle

Here the particle is unified encapsulation, a brief introduction to the relevant properties: positionBase: the initial position of the particle generationnew THREE.Vector3
positionRadius: rounded cornerspositionSpread: Particle rangenew THREE.Vector3
velocityBase: Speed Of motion Speed in three dimensional coordinate directionnew THREE.Vector3
velocityBase: Range of motionnew THREE.Vector3
accelerationBase: Acceleration of motion Acceleration in the direction of three dimensional coordinatesnew THREE.Vector3
particleTexture: mapsizeTween: particle sizeopacityTween: Particle transparencycolorTweenParticlesPerSecond: specifies the number of particlesparticleDeathAge: Single particle survival timeemitterDeathAge: Animation durationCopy the code

snow

Snow particle object: The related properties are described above, mainly through mapping and particle animationCopy the code
snow :
  {
    positionStyle    : Type.CUBE,
    positionBase     : new THREE.Vector3( 0.200.0 ),
    positionSpread   : new THREE.Vector3( 400.0.400 ),

    velocityStyle    : Type.CUBE,
    velocityBase     : new THREE.Vector3( 50, -200.0 ),
    velocitySpread   : new THREE.Vector3( 50.200.50 ),
    accelerationBase : new THREE.Vector3( 0, -10.0 ),

    angleBase               : 0.angleSpread             : 720.angleVelocityBase       :  0.angleVelocitySpread     : 60.particleTexture : textureLoader.load(gAppPath+'images/snowflake.png' ),

    sizeTween    : new Tween( [0.0.25], [4.5]),colorBase   : new THREE.Vector3(0.66.1.0.0.9), // H,S,L
    opacityTween : new Tween( [2.3], [0.8.0]),particlesPerSecond : 500.particleDeathAge   : 1.0.emitterDeathAge    : 60
  },
Copy the code

fireflies

Firefly particle object: The related properties are described above, mainly through mapping and particle animationCopy the code
fireflies :
  {
    positionStyle  : Type.CUBE,
    positionBase   : new THREE.Vector3( 0.100.0 ),
    positionSpread : new THREE.Vector3( 400.200.400 ),

    velocityStyle  : Type.CUBE,
    velocityBase   : new THREE.Vector3( 0.0.0 ),
    velocitySpread : new THREE.Vector3( 60.20.60 ),



    particleTexture : textureLoader.load(gAppPath+'images/spark.png' ),

    sizeBase   : 30.0.sizeSpread : 10.0.opacityTween : new Tween([0.0.1.0.1.1.2.0.2.1.3.0.3.1.4.0.4.1.5.0.5.1.6.0.6.1],
      [0.2.0.2.1.0.1.0.0.2.0.2.1.0.1.0.0.2.0.2.1.0.1.0.0.2]),colorBase   : new THREE.Vector3(0.30.1.0.0.6), // H,S,L
    colorSpread : new THREE.Vector3(0.3.0.0.0.0),

    particlesPerSecond : 20.particleDeathAge   : 6.1.emitterDeathAge    : 600
  },
Copy the code

smoke

Smoke particle object: The related properties are described above, mainly through mapping and particle animationCopy the code
smoke :
  {
    positionStyle    : Type.CUBE,
    positionBase     : new THREE.Vector3( 0.0.0 ),
    positionSpread   : new THREE.Vector3( 2.0.2 ),

    velocityStyle    : Type.CUBE,
    velocityBase     : new THREE.Vector3( 0.40.0 ),
    velocitySpread   : new THREE.Vector3( 20.40.20 ),
    accelerationBase : new THREE.Vector3( 0, -10.0 ),

    particleTexture : textureLoader.load(gAppPath+'images/smokeparticle.png'),
    speedBase     : 10.speedSpread   : 10.angleBase               : 0.angleSpread             : 720.angleVelocityBase       : 0.angleVelocitySpread     : 720.sizeTween    : new Tween( [0.1], [32.128]),opacityTween : new Tween( [0.8.2], [0.5.0]),colorTween   : new Tween( [0.4.1], [ new THREE.Vector3(0.0.0.2), new THREE.Vector3(0.0.0.5)),particlesPerSecond : 6.particleDeathAge   : 2.0.emitterDeathAge    : 5
  },
Copy the code

The explosion

Explosive particle object: The related properties are described above, mainly through mapping and particle animationCopy the code
fireball :
  {
    positionStyle  : Type.SPHERE,
    positionBase   : new THREE.Vector3( 0.50.0 ),
    positionRadius : 2.velocityStyle : Type.SPHERE,
    speedBase     : 10.speedSpread   : 50.particleTexture : textureLoader.load(gAppPath+'images/smokeparticle.png' ),

    sizeTween    : new Tween( [0.0.1], [1.50]),opacityTween : new Tween( [0.7.1], [1.0]),colorBase    : new THREE.Vector3(0.02.1.0.4),
    blendStyle   : THREE.AdditiveBlending,

    particlesPerSecond : 300.particleDeathAge   : 0.5.emitterDeathAge    : 60
  },
Copy the code

The starry sky

Star particle object: The related properties are described above, mainly through mapping and particle animationCopy the code
starfield :
  {
    positionStyle    : Type.CUBE,
    positionBase     : new THREE.Vector3( 0.100.0 ),
    positionSpread   : new THREE.Vector3( 400.100.400 ),

    velocityStyle    : Type.CUBE,
    velocityBase     : new THREE.Vector3( 0.0.0 ),
    velocitySpread   : new THREE.Vector3( 0.5.0.5.0.5 ),

    angleBase               : 0.angleSpread             : 720.angleVelocityBase       : 0.angleVelocitySpread     : 4.particleTexture : textureLoader.load(gAppPath+'images/spikey.png' ),

    sizeBase    : 10.0.sizeSpread  : 2.0.colorBase   : new THREE.Vector3(0.15.1.0.0.9), // H,S,L
    colorSpread : new THREE.Vector3(0.00.0.0.0.2),
    opacityBase : 1.particlesPerSecond : 1000.particleDeathAge   : 60.0.emitterDeathAge    : 0.1
  },
Copy the code

The rain

Rain particle object: The related properties are described above, mainly through mapping and particle animationCopy the code
rain :
  {
    positionStyle    : Type.CUBE,
    positionBase     : new THREE.Vector3( 0.200.0 ),
    positionSpread   : new THREE.Vector3( 400.0.400 ),

    velocityStyle    : Type.CUBE,
    velocityBase     : new THREE.Vector3( 0, -700.0 ),
    velocitySpread   : new THREE.Vector3( 10.50.10 ),
    accelerationBase : new THREE.Vector3( 0, -10.0 ),

    particleTexture : textureLoader.load(gAppPath+'images/raindrop2flip.png' ),

    sizeBase    : 8.sizeSpread  : 4.0.colorBase   : new THREE.Vector3(0.66.1.0.0.75), // H,S,L
    colorSpread : new THREE.Vector3(0.0.0.0.1),
    opacityBase : 0.4.particlesPerSecond : 600.particleDeathAge   : 1.0.emitterDeathAge    : 60
  },
Copy the code

The flame

Fire particle object: The properties are described above, mainly through mapping and particle animationCopy the code
candle :
  {
    positionStyle  : Type.SPHERE,
    positionBase   : new THREE.Vector3( 0.50.0 ),
    positionRadius : 2.velocityStyle  : Type.CUBE,
    velocityBase   : new THREE.Vector3(0.30.0),
    velocitySpread : new THREE.Vector3(20.0.20),
    speedBase     : 10.speedSpread   : 10.particleTexture : textureLoader.load(gAppPath+'images/smokeparticle.png' ),

    sizeTween    : new Tween( [0.0.3.1.2], [20.15.1]),opacityTween : new Tween( [0.9.1.5], [1.0]),colorTween   : new Tween( [0.5.1.0], [ new THREE.Vector3(0.02.1.0.5), new THREE.Vector3(0.05.1.0)),blendStyle : THREE.AdditiveBlending,

    particlesPerSecond : 600.particleDeathAge   : 104.emitterDeathAge    : 10
  }
Copy the code

cloud

Cloud particle object: The related properties are described above, mainly through mapping and particle animationCopy the code
clouds :
  {
    positionStyle  : Type.CUBE,
    positionBase   : new THREE.Vector3( -100.100.0 ),
    positionSpread : new THREE.Vector3( 0.10.60 ),

    velocityStyle  : Type.CUBE,
    velocityBase   : new THREE.Vector3( 100.0.0 ),
    velocitySpread : new THREE.Vector3( 100.0.0 ),

    particleTexture : textureLoader.load(gAppPath+'images/smokeparticle.png'),

    sizeBase     : 80.0.sizeSpread   : 100.0.colorBase    : new THREE.Vector3(0.0.0.0.1.0), // H,S,L
    opacityTween : new Tween([0.1.4.5], [0.1.1.0]),

    particlesPerSecond : 100.particleDeathAge   : 10.0.emitterDeathAge    : 60
  },
Copy the code

haze

Haze particle object: Related properties are described above, mainly through mapping and particle animationCopy the code
haze: / / the fog haze
  {
    positionStyle: Type.CUBE,
    positionBase: new THREE.Vector3(0.50.0),
    positionSpread: new THREE.Vector3(400.100.400),

    velocityStyle: Type.CUBE,
    velocityBase: new THREE.Vector3(0.0.0),
    velocitySpread: new THREE.Vector3(100.5.0.5.100.5),

    angleBase: 0.angleSpread: 0.angleVelocityBase: 0.angleVelocitySpread: 4.particleTexture: textureLoader.load(gAppPath + 'images/smoke512.png'),

    sizeBase: 1000.0.sizeSpread: 2.0.colorBase: new THREE.Vector3(0.15.1.0.0), // H,S,L
    colorSpread: new THREE.Vector3(0.00.0.0.0.2),
    opacityBase: 0.15.particlesPerSecond: 1000.particleDeathAge: 60.0.emitterDeathAge: 0.1
  },
Copy the code

Particle class

Here, through the form of class, the particle system has made an overall encapsulation, and I will analyze most of the ideas. Class is divided into: -tween class (according to the time interval and value interval of particle object sizeTween, opacityTween and colorBase, ParticleEngine ParticleEngine ParticleEngine ParticleEngine ParticleEngine ParticleEngine ParticleEngine ParticleEngineCopy the code

Tween

Call example: new Tween([0, 1], [1, 10]) The main function of this class is to obtain the values of size, color, and opacity by passing t into timeArrayCopy the code
class Tween {
  constructor(timeArray, valueArray) {
    this.times = timeArray || []
    this.values = valueArray || []
  }

  lerp(t) {
    var i = 0
    var n = this.times.length
    while (i < n && t > this.times[i]) {
      i++
    }
    if (i == 0) {
      return this.values[0]}if (i == n) {
      return this.values[n - 1]}var p = (t - this.times[i - 1)/(this.times[i] - this.times[i - 1])
    if (this.values[0] instanceof THREE.Vector3) {
      return this.values[i - 1].clone().lerp(this.values[i], p)
    } else // its a float
    {
      return this.values[i - 1] + p * (this.values[i] - this.values[i - 1])}}}Copy the code

Particle

Var particle = new particle () Resolution: This class is used to create particles, just single particles. By randomly generating the position of the particle in a specific range, continuously accumulating vector scalars, vector scalars constantly increasing simulation acceleration, control Angle (draw in custom shader), control size, color, transparencyCopy the code
class Particle {
  constructor() {
    this.position = new THREE.Vector3() // Particle position
    this.velocity = new THREE.Vector3() // Scalar vectors
    this.acceleration = new THREE.Vector3()
    this.angle = 0 / / Angle
    this.angleVelocity = 0 
    this.angleAcceleration = 0 
    this.size = 16.0
    this.color = new THREE.Color()
    this.opacity = 1.0
    this.age = 0 // Survival time
    this.alive = 0 // Whether to display
  }

  update(dt) { // Particle property update function
    this.position.add(this.velocity.clone().multiplyScalar(dt))// Add the vectors and move the particles
    this.velocity.add(this.acceleration.clone().multiplyScalar(dt))// Add the sum of vectors to simulate acceleration

    this.angle += this.angleVelocity * 0.01745329251 * dt / / Angle
    this.angleVelocity += this.angleAcceleration * 0.01745329251 * dt / / angular velocity

    this.age += dt // Add the particle lifetime

    if (this.sizeTween.times.length > 0) {
      this.size = this.sizeTween.lerp(this.age) / / size
    }

    if (this.colorTween.times.length > 0) {
      var colorHSL = this.colorTween.lerp(this.age)
      this.color = new THREE.Color().setHSL(colorHSL.x, colorHSL.y, colorHSL.z)/ / color
    }

    if (this.opacityTween.times.length > 0) {
      this.opacity = this.opacityTween.lerp(this.age)/ / transparency}}}Copy the code

ParticleEngine

Particle class functions: -setvalues Initializes the properties of the particle class by particle type. -createparticle creates a particle, randomly generating the values of its position, color, Angle, size, transparency, etc. -Initialize Initializes the particle scene. Generate all particles by the number of particles and add the -update particle property update function with the scene, Particle update loop system - destroy Destroy particle - randomVector3 Randomly generates a 3D coordinate based on a specific range and initial position - randomValue Generates a random Angle based on the initial Angle and the range of anglesCopy the code
Examples of global particle calls:import {ParticleEngine} from 'zhdPartice'
import ParticleEngineExamples from 'zhdParticleExamples'

initParticle = function () {
  this.particle = new ParticleEngine()
  this.particle.setValues(ParticleEngineExamples.candle, {
    positionBase: new THREE.Vector3(0.0.0})),this.particle.initialize(this.scene)
  this.renderFunction.push(() = > {
    if (this.particle) this.particle.update(0.01)})}Copy the code

shader

The shader code is as follows, not expanded here.Copy the code
const particleVertexShader =
  [
    'attribute vec3  customColor;'.'attribute float customOpacity; '.'attribute float customSize; '.'attribute float customAngle; '.'attribute float customVisible; '.// float used as boolean (0 = false, 1 = true)
    'varying vec4  vColor;'.'varying float vAngle; '.'void main()'.'{'.'If (customVisible > 0.5)'.// true
    'vColor = vec4( customColor, customOpacity ); '.// set color associated to vertex; use later in fragment shader.
    'else'.// false
    'vColor = vec4,0,0,0 (0); '.// make particle invisible.

    'vAngle = customAngle; '.'vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); '.'gl_PointSize = customSize * (300.0 / length(mvposition.xyz)); '.// scale particles as objects in 3D space
    'gl_Position = projectionMatrix * mvPosition; '.'} '
  ].join('\n')

const particleFragmentShader =
  [
    'uniform sampler2D mytexture; '.'varying vec4 vColor; '.'varying float vAngle; '.'void main()'.'{'.'gl_FragColor = vColor; '.'float c = cos(vAngle); '.'float s = sin(vAngle); '.Vec2 rotatedUV = vec2(c * (gl_pointcoord.x-0.5) + s * (gl_pointcoord.y-0.5) + 0.5,'.'c * * (gl_PointCoord. Y - 0.5) - s (gl_PointCoord. X - 0.5 + 0.5); '.// rotate UV coordinates to rotate texture
    'vec4 rotatedTexture = texture2D( mytexture,  rotatedUV );'.'gl_FragColor = gl_FragColor * rotatedTexture; '.// sets an otherwise white particle texture to desired color
    '} '
  ].join('\n')
Copy the code

setValues

Generate the initialization properties of the particle through the type and the new object.Copy the code
setValues(parameters,params) {
  / * * * *@param Whether the mugen loops indefinitely *@param Number of particlesPerSecond particles *@param ParticleDeathAge Lifetime of each particle *@param EmitterDeathAge Duration mugen valid for false *@param PositionBase obj Particle system initial position xyz *@param PositionSpread OBj Particle range xyz *@param The velocityBase particle moves in the xzy direction with a velocity xyz *@param VelocitySpread The range of motion of the particle along the xzy direction */
  this.mugen = params.mugen||false // Infinite loop
  if (parameters === undefined) {
    return
  }
  let obj=Object.assign(parameters,params) // Override the original attribute values
  this.sizeTween = new Tween() / / size
  this.colorTween = new Tween() / / color
  this.opacityTween = new Tween()/ / transparency

  for (var key in obj) { // Initialize parameter assignment
    this[key] = obj[key]
  }

  Particle.prototype.sizeTween = this.sizeTween
  Particle.prototype.colorTween = this.colorTween
  Particle.prototype.opacityTween = this.opacityTween

  this.particleArray = [] // Particle collection
  this.emitterAge = 0.0
  this.emitterAlive = true
  this.particleCount = this.particlesPerSecond * Math.min(this.particleDeathAge, this.emitterDeathAge)// Number of particles
  // Material dependent
  this.particleGeometry = new THREE.BufferGeometry()
  this.particleMaterial = new THREE.ShaderMaterial(
    {
      uniforms: {
        mytexture: {value: this.particleTexture},
      },
      vertexShader: particleVertexShader,
      fragmentShader: particleFragmentShader,
      blending: THREE.AdditiveBlending,
      depthTest: false.transparent: true.vertexColors: true})}Copy the code

createParticle

Create a particle. Initialize the position, Angle, size, transparency, color, life time, display and other properties of the particle randomly generated within a specific range according to the properties of the particle object. The corresponding annotations have been made in the code. Because of the close correlation, it is necessary to combine the code before and after to understand the code ~~Copy the code
createParticle() {
  var particle = new Particle() // Initializes the creation of the particle class
  // Initializes random generation of corresponding attribute values according to the particle type
  if (this.positionStyle == Type.CUBE) {
    particle.position = this.randomVector3(this.positionBase, this.positionSpread)/ / position
  }
  if (this.positionStyle == Type.SPHERE) {
    var z = 2 * Math.random() - 1
    var t = 6.2832 * Math.random()
    var r = Math.sqrt(1 - z * z)
    var vec3 = new THREE.Vector3(r * Math.cos(t), r * Math.sin(t), z)
    particle.position = new THREE.Vector3().addVectors(this.positionBase, vec3.multiplyScalar(this.positionRadius))
  }

  if (this.velocityStyle == Type.CUBE) {
    particle.velocity = this.randomVector3(this.velocityBase, this.velocitySpread)// Vector scalars
  }
  if (this.velocityStyle == Type.SPHERE) {
    var direction = new THREE.Vector3().subVectors(particle.position, this.positionBase)
    var speed = this.randomValue(this.speedBase, this.speedSpread)
    particle.velocity = direction.normalize().multiplyScalar(speed)
  }

  particle.acceleration = this.randomVector3(this.accelerationBase, this.accelerationSpread)// Scalar summation vector

  particle.angle = this.randomValue(this.angleBase, this.angleSpread)/ / Angle
  particle.angleVelocity = this.randomValue(this.angleVelocityBase, this.angleVelocitySpread)
  particle.angleAcceleration = this.randomValue(this.angleAccelerationBase, this.angleAccelerationSpread)

  particle.size = this.randomValue(this.sizeBase, this.sizeSpread)/ / size

  var color = this.randomVector3(this.colorBase, this.colorSpread)/ / color
  particle.color = new THREE.Color().setHSL(color.x, color.y, color.z)

  particle.opacity = this.randomValue(this.opacityBase, this.opacitySpread)/ / transparency

  particle.age = 0// Survival time
  particle.alive = 0 // Whether to display

  return particle
}
Copy the code

initialize

Initialize the particle scene, generate the BufferGeometry and material generation point particle set through traversal, and add it to the scene. Record all the attributes of each particle, and control the values of the related attributes of the particle through setAttribute. The custom related attributes indirectly affect the particle color, explicit and implicit, size, transparency and other attributes in the custom shaderCopy the code
initialize(scene) {
  var positions = []
  var customVisibles = []
  var customColor = []
  var customOpacity = []
  var customSize = []
  var customAngle = []
  for (var i = 0; i < this.particleCount; i++) { // Iterates to generate the corresponding number of BufferGeometry
    this.particleArray[i] = this.createParticle()
    positions.push(this.particleArray[i].position.x)
    positions.push(this.particleArray[i].position.y)
    positions.push(this.particleArray[i].position.z)
    // Custom shader related
    customVisibles.push(this.particleArray[i].alive)
    customColor.push(this.particleArray[i].color.r)
    customColor.push(this.particleArray[i].color.g)
    customColor.push(this.particleArray[i].color.b)
    customOpacity.push(this.particleArray[i].opacity)
    customSize.push(this.particleArray[i].size)
    customAngle.push(this.particleArray[i].angle)
  }

  this.positions = positions // Array of positions
  this.customVisibles = customVisibles // Implicit array
  this.customColor = customColor// Color array
  this.customOpacity = customOpacity// Transparency array
  this.customSize = customSize// Size array
  this.customAngle = customAngle// Angle array
  // Sets the attribute attribute of BufferGeometry
  this.particleGeometry.setAttribute('position'.new THREE.Float32BufferAttribute(this.positions, 3))
  this.particleGeometry.setAttribute('customVisible'.new THREE.Float32BufferAttribute(this.customVisibles, 1))
  this.particleGeometry.setAttribute('customColor'.new THREE.Float32BufferAttribute(this.customColor, 3))
  this.particleGeometry.setAttribute('customOpacity'.new THREE.Float32BufferAttribute(this.customOpacity, 1))
  this.particleGeometry.setAttribute('customSize'.new THREE.Float32BufferAttribute(this.customSize, 1))
  this.particleGeometry.setAttribute('customAngle'.new THREE.Float32BufferAttribute(this.customAngle, 1))


  this.particleMaterial.blending = this.blendStyle
  if (this.blendStyle ! == THREE.NormalBlending) {this.particleMaterial.depthTest = false
  }
  / / involves
  this.particleMesh = new THREE.Points(this.particleGeometry, this.particleMaterial)
  this.particleMesh.dynamic = true
  this.particleMesh.sortParticles = true
  scene.add(this.particleMesh)
}
Copy the code

update

Particle motion function analysis: update corresponding particle properties and shaders by traversing particles, record invalid particle subscripts, and generate new particles by subscripts. Particle transition from nothing: generate the corresponding percentage of particles according to the existence time of the particle scene and the end time of the particle scene, and control whether the particle animation stops within the specified time or continues indefinitely according to the infinite loop. Particlearray. update Updates the positions of particles by subscripting them in groups of threeCopy the code
update(dt) {
  var recycleIndices = []
  for (var i = 0; i < this.particleCount; i++) {// Walk through the particles in the scene
    if (this.particleArray[i].alive) {
      this.particleArray[i].update(dt) // Particle properties updated
      if (this.particleArray[i].age > this.particleDeathAge) { // Determine whether the particle has survived for longer than the specified time
        this.particleArray[i].alive = 0.0 // Hide particles
        recycleIndices.push(i)// Void particle index array
      }
      // Update the shader specific properties array
      this.customVisibles[i] = this.particleArray[i].alive
      this.customColor[i * 3] = this.particleArray[i].color.r
      this.customColor[i * 3 + 1] = this.particleArray[i].color.g
      this.customColor[i * 3 + 2] = this.particleArray[i].color.b
      this.customOpacity[i] = this.particleArray[i].opacity
      this.customSize[i] = this.particleArray[i].size
      this.customAngle[i] = this.particleArray[i].angle
    }
  }
   // Sets the attribute attribute of BufferGeometry, shader dependent, color, size, position, and explicit and implicit effects
  this.particleGeometry.setAttribute('customVisible'.new THREE.Float32BufferAttribute(this.customVisibles, 1))
  this.particleGeometry.setAttribute('customColor'.new THREE.Float32BufferAttribute(this.customColor, 3))
  this.particleGeometry.setAttribute('customOpacity'.new THREE.Float32BufferAttribute(this.customOpacity, 1))
  this.particleGeometry.setAttribute('customSize'.new THREE.Float32BufferAttribute(this.customSize, 1))
  this.particleGeometry.setAttribute('customAngle'.new THREE.Float32BufferAttribute(this.customAngle, 1))

  this.particleGeometry.attributes.customVisible.needsUpdate = true
  this.particleGeometry.attributes.customColor.needsUpdate = true
  this.particleGeometry.attributes.customOpacity.needsUpdate = true
  this.particleGeometry.attributes.customSize.needsUpdate = true
  this.particleGeometry.attributes.customAngle.needsUpdate = true

  if (!this.emitterAlive) return // The entire particle system is alive (particle animation time)
  // Control the display of some particles of all particles, the longer the longer the number of particles, until all particles are displayed
  if (this.emitterAge < this.particleDeathAge) { // If the time is not finished
    var startIndex = Math.round(this.particlesPerSecond * (this.emitterAge + 0))
    var endIndex = Math.round(this.particlesPerSecond * (this.emitterAge + dt))
    if (endIndex > this.particleCount) { // Determine the number of particles
      endIndex = this.particleCount
    }

    for (var i = startIndex; i < endIndex; i++) { //
      this.particleArray[i].alive = 1.0}}for (var j = 0; j < recycleIndices.length; j++) // Failed particles are regenerated
  {
    var i = recycleIndices[j] // Get index subscript
    this.particleArray[i] = this.createParticle() // Recreate the particle
    this.particleArray[i].alive = 1.0 // Display particles
  }
  // Particle position changes
  for (var j = 0; j < this.particleCount; j++) {
    this.positions[j * 3] = this.particleArray[j].position.x
    this.positions[j * 3 + 1] = this.particleArray[j].position.y
    this.positions[j * 3 + 2] = this.particleArray[j].position.z
  }
  // In groups of three, update the particle positions of the entire BufferGeometry
  this.particleGeometry.setAttribute('position'.new THREE.Float32BufferAttribute(this.positions, 3))
  // Particle animation time accumulated
  this.emitterAge += dt
  if (!this.mugen) { // Whether the loop is infinite
    if (this.emitterAge > this.emitterDeathAge) this.emitterAlive = false}}Copy the code

destroy

Destruction of the particleCopy the code
destroy(scene) {
  scene.remove(this.particleMesh)
}
Copy the code

randomVector3

Generate a random 3 D coordinate based on a specific range and initial positionCopy the code
randomVector3(base, spread) {
  var rand3 = new THREE.Vector3(Math.random() - 0.5.Math.random() - 0.5.Math.random() - 0.5)
  return new THREE.Vector3().addVectors(base, new THREE.Vector3().multiplyVectors(spread, rand3))
}
Copy the code

randomValue

Generate a random Angle based on the initial Angle and the range of anglesCopy the code
randomValue(base, spread) {
  return base + spread * (Math.random() - 0.5)}Copy the code

conclusion

Not easy to write, pig sigh! It took me a whole day to write this article. I tried my best to annotate the whole idea of the article. The amount of code was a bit much, but full of work! Hope the students who have harvest can gently point a praise ~

Of course, if you have any comments and don’t understand the place, you are welcome to put forward in the comment area, I will learn to make corrections ~~